Python Automation for Beginners: A Practical Guide
Tutorials

Python Automation for Beginners: A Practical Guide

6 min read
35 Views
Share:

Python is the perfect language for automating repetitive tasks that steal hours from your week: renaming files, scraping websites, sending bulk emails, interacting with APIs, generating reports. In this practical guide, you'll learn to automate real tasks with scripts you can start using today.

Prerequisites

Install Python 3.10+ and set up a virtual environment:

python -m venv myenv
source myenv/bin/activate  # macOS/Linux
myenv\Scripts\activate     # Windows

pip install requests beautifulsoup4 openpyxl python-dotenv

1. File operations automation

Organize files automatically by type:

import os
import shutil
from pathlib import Path

def organize_downloads(folder_path):
    """Organize files into subfolders by type."""
    categories = {
        'Images': ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp'],
        'Documents': ['.pdf', '.doc', '.docx', '.txt', '.xlsx', '.csv'],
        'Videos': ['.mp4', '.avi', '.mkv', '.mov'],
        'Code': ['.py', '.js', '.html', '.css', '.json'],
        'Archives': ['.zip', '.rar', '.7z', '.tar', '.gz'],
    }

    folder = Path(folder_path)
    moved = 0

    for file in folder.iterdir():
        if file.is_dir():
            continue

        ext = file.suffix.lower()
        dest = 'Other'
        for cat, exts in categories.items():
            if ext in exts:
                dest = cat
                break

        dest_folder = folder / dest
        dest_folder.mkdir(exist_ok=True)
        shutil.move(str(file), str(dest_folder / file.name))
        moved += 1
        print(f"  {file.name} -> {dest}/")

    print(f"\n{moved} files organized")

organize_downloads(os.path.expanduser("~/Downloads"))

Bulk rename files

from pathlib import Path

def rename_photos(folder, prefix="photo"):
    """Rename files sequentially: photo_001.jpg, photo_002.jpg..."""
    folder = Path(folder)
    images = sorted(
        [f for f in folder.iterdir() if f.suffix.lower() in ('.jpg', '.png')],
        key=lambda x: x.stat().st_mtime
    )
    for i, img in enumerate(images, 1):
        new_name = f"{prefix}_{i:03d}{img.suffix.lower()}"
        img.rename(folder / new_name)
        print(f"  {img.name} -> {new_name}")

rename_photos("./my_photos", prefix="vacation_2026")

2. Web scraping with BeautifulSoup

import requests
from bs4 import BeautifulSoup
import csv
from datetime import datetime

def scrape_hackernews():
    """Extract titles and links from Hacker News."""
    url = "https://news.ycombinator.com/"
    headers = {'User-Agent': 'Mozilla/5.0 (compatible; MyBot/1.0)'}

    response = requests.get(url, headers=headers, timeout=10)
    response.raise_for_status()

    soup = BeautifulSoup(response.text, 'html.parser')
    stories = []

    for item in soup.select('.titleline > a'):
        stories.append({
            'title': item.text,
            'url': item.get('href', ''),
            'scraped_at': datetime.now().isoformat()
        })

    filename = f"hackernews_{datetime.now().strftime('%Y%m%d')}.csv"
    with open(filename, 'w', newline='', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=['title', 'url', 'scraped_at'])
        writer.writeheader()
        writer.writerows(stories)

    print(f"Scraped {len(stories)} stories -> {filename}")

scrape_hackernews()

Important: Always respect robots.txt and add delays between requests with time.sleep(1). Read more about robots.txt and Python.

3. Working with APIs

import requests
import os
from dotenv import load_dotenv

load_dotenv()

def get_weather(city):
    """Get current weather using OpenWeatherMap API."""
    api_key = os.getenv('OPENWEATHER_API_KEY')
    if not api_key:
        print("Error: Set OPENWEATHER_API_KEY in your .env file")
        return

    url = "https://api.openweathermap.org/data/2.5/weather"
    params = {'q': city, 'appid': api_key, 'units': 'metric'}

    try:
        resp = requests.get(url, params=params, timeout=10)
        resp.raise_for_status()
        data = resp.json()

        print(f"\nWeather in {data['name']}:")
        print(f"  Temperature: {data['main']['temp']}°C")
        print(f"  Humidity: {data['main']['humidity']}%")
        print(f"  Conditions: {data['weather'][0]['description']}")
    except requests.exceptions.HTTPError as e:
        print(f"HTTP Error: {e}")
    except requests.exceptions.ConnectionError:
        print("Error: No internet connection")

get_weather("London")

4. Excel report generation

from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment
from datetime import datetime

def generate_sales_report(data):
    """Generate a formatted Excel sales report."""
    wb = Workbook()
    ws = wb.active
    ws.title = "Sales Report"

    # Header styles
    header_font = Font(bold=True, color="FFFFFF", size=12)
    header_fill = PatternFill(start_color="1e3a5f", fill_type="solid")

    # Title
    ws.merge_cells('A1:E1')
    ws['A1'] = f"Sales Report - {datetime.now().strftime('%B %Y')}"
    ws['A1'].font = Font(bold=True, size=16)

    # Headers
    headers = ['Product', 'Quantity', 'Unit Price', 'Total', 'Date']
    for col, header in enumerate(headers, 1):
        cell = ws.cell(row=3, column=col, value=header)
        cell.font = header_font
        cell.fill = header_fill

    # Data rows
    grand_total = 0
    for row, sale in enumerate(data, 4):
        total = sale['qty'] * sale['price']
        grand_total += total
        ws.cell(row=row, column=1, value=sale['product'])
        ws.cell(row=row, column=2, value=sale['qty'])
        ws.cell(row=row, column=3, value=sale['price']).number_format = '$#,##0.00'
        ws.cell(row=row, column=4, value=total).number_format = '$#,##0.00'
        ws.cell(row=row, column=5, value=sale['date'])

    # Grand total
    total_row = len(data) + 4
    ws.cell(row=total_row, column=3, value="TOTAL:").font = Font(bold=True)
    ws.cell(row=total_row, column=4, value=grand_total).font = Font(bold=True)

    for col in ['A', 'B', 'C', 'D', 'E']:
        ws.column_dimensions[col].width = 18

    filename = f"sales_{datetime.now().strftime('%Y%m%d')}.xlsx"
    wb.save(filename)
    print(f"Report generated: {filename}")

sales = [
    {'product': 'Laptop', 'qty': 5, 'price': 899.99, 'date': '2026-02-01'},
    {'product': 'Monitor 27"', 'qty': 12, 'price': 349.99, 'date': '2026-02-05'},
    {'product': 'Keyboard', 'qty': 25, 'price': 79.99, 'date': '2026-02-10'},
]
generate_sales_report(sales)

5. Sending automated emails

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import os
from dotenv import load_dotenv

load_dotenv()

def send_email(to, subject, html_body):
    sender = os.getenv('EMAIL_USER')
    password = os.getenv('EMAIL_PASSWORD')

    msg = MIMEMultipart()
    msg['From'] = sender
    msg['To'] = to
    msg['Subject'] = subject
    msg.attach(MIMEText(html_body, 'html'))

    try:
        with smtplib.SMTP('smtp.gmail.com', 587) as server:
            server.starttls()
            server.login(sender, password)
            server.send_message(msg)
        print(f"Email sent to {to}")
    except Exception as e:
        print(f"Error: {e}")

send_email("client@example.com", "Monthly Report", "

February 2026

See attached.

")

For Gmail, generate an App Password instead of using your regular password.

Best practices

  1. Use environment variables for credentials (.env + python-dotenv). Never hardcode passwords.
  2. Always handle errors: Use try/except for network, file, and API operations.
  3. Add logging: Use Python's logging module instead of print() in production.
  4. Use virtual environments: Each project with its own venv avoids dependency conflicts.
  5. Respect rate limits: In web scraping, respect robots.txt and add delays between requests.

Next steps

J
Written by
Jesús García

Apasionado por la tecnologia y las finanzas personales. Escribo sobre innovacion, inteligencia artificial, inversiones y estrategias para mejorar tu economia. Mi objetivo es hacer que temas complejos sean accesibles para todos.

Share post:

Related posts

Comments

Leave a comment

Recommended Tools

The ones we use in our projects

Affiliate links. No extra cost to you.

Need technology services?

We offer comprehensive web development, mobile apps, consulting, and more.

Web Development Mobile Apps Consulting