Automating Your Workflow with Python: 5 Real‑World Scripts

You know that feeling when you stare at a mountain of repetitive tasks and wonder if there’s a secret button that says “Do it for me”? Spoiler: there is, and it’s called Python. In 2024 every dev, data‑enthusiast, or even a hobbyist who juggles emails, file renames, and API calls can shave hours off their week with a few well‑placed scripts. I’ve been there—spending a Friday night manually moving screenshots into dated folders—until I decided to let code do the grunt work. Below are five scripts that I actually use in my day‑to‑day, each solving a real problem without pulling my hair out.

1. Bulk Rename Photos by EXIF Date

Why it matters

Your phone’s camera tags every picture with EXIF metadata, which includes the exact timestamp the shot was taken. Yet after a weekend trip you end up with files named IMG_1234.jpg, IMG_1235.jpg, etc. Sorting them chronologically becomes a nightmare.

The script

import os
from datetime import datetime
from PIL import Image
from PIL.ExifTags import TAGS

def get_exif_date(path):
    img = Image.open(path)
    exif = img._getexif()
    if not exif:
        return None
    for tag, value in exif.items():
        decoded = TAGS.get(tag, tag)
        if decoded == "DateTimeOriginal":
            return datetime.strptime(value, "%Y:%m:%d %H:%M:%S")
    return None

folder = "/path/to/photos"
for filename in os.listdir(folder):
    if not filename.lower().endswith(('.jpg', '.jpeg')):
        continue
    full_path = os.path.join(folder, filename)
    date = get_exif_date(full_path)
    if date:
        new_name = date.strftime("%Y%m%d_%H%M%S") + ".jpg"
        os.rename(full_path, os.path.join(folder, new_name))
        print(f"Renamed {filename} → {new_name}")

How it helps

Run it once after a shoot and every file instantly tells you when it was taken. No more guessing which sunset photo belongs to which day. I keep a copy of the script in my ~/scripts folder and fire it up with a single alias: renamephotos.

2. Auto‑Generate Weekly Status Emails

Why it matters

Every Monday I need to send a brief status email to my team, summarizing what I completed last week and what’s on the docket. Typing the same boilerplate over and over feels like a waste of brainpower.

The script

import smtplib
from email.mime.text import MIMEText
from datetime import date, timedelta

def build_body():
    today = date.today()
    last_monday = today - timedelta(days=today.weekday() + 7)
    body = f"""Hey team,

Here’s my weekly snapshot (covering {last_monday} – {last_monday + timedelta(days=6)}):
- Completed: Refactored the data‑pipeline module.
- In progress: Adding unit tests for the new API endpoints.
- Blockers: Waiting on the design mockups.

Enjoy the week!
— Maya
"""
    return body

msg = MIMEText(build_body())
msg["Subject"] = "Weekly Status – Maya"
msg["From"] = "[email protected]"
msg["To"] = "[email protected]"

with smtplib.SMTP("smtp.logzly.com", 587) as server:
    server.starttls()
    server.login("[email protected]", "your_app_password")
    server.send_message(msg)
    print("Status email sent.")

How it helps

Just hit python weekly_status.py and the email flies out. I tweak the build_body function each week, but the scaffolding stays the same. It’s a tiny time‑saver that also guarantees a consistent format.

3. Scrape Daily Tech Headlines

Why it matters

I love staying on top of AI breakthroughs, but opening three different news sites every morning is a chore. A quick scraper can pull the headlines into a single markdown file that I can read over coffee.

The script

import requests
from bs4 import BeautifulSoup

sources = {
    "TechCrunch": "https://techcrunch.com/tag/artificial-intelligence/",
    "The Verge": "https://www.theverge.com/ai",
    "Wired": "https://www.wired.com/category/ai/",
}

def fetch_headlines(url):
    resp = requests.get(url, timeout=10)
    soup = BeautifulSoup(resp.text, "html.parser")
    # Most sites use <h2> for article titles; adjust if needed
    return [h.get_text(strip=True) for h in soup.find_all("h2")[:5]]

with open("daily_ai_headlines.md", "w") as f:
    f.write("# Daily AI Headlines\n\n")
    for name, link in sources.items():
        f.write(f"## {name}\n")
        for title in fetch_headlines(link):
            f.write(f"- {title}\n")
        f.write("\n")
print("Headlines saved to daily_ai_headlines.md")

How it helps

Run it each morning, open the markdown file, and you have a curated list without the click‑fatigue. I even set a cron job to email the file to myself at 7 am. The script is deliberately simple; if a site changes its HTML layout you just tweak the find_all selector.

4. Convert CSV to JSON for API Mocking

Why it matters

When building a front‑end prototype I often need a quick JSON payload that mirrors a CSV export from our analytics team. Manually copy‑pasting rows into a JSON editor is error‑prone.

The script

import csv
import json
import sys

def csv_to_json(csv_path, json_path):
    with open(csv_path, newline='', encoding='utf-8') as csvfile:
        reader = csv.DictReader(csvfile)
        rows = list(reader)
    with open(json_path, "w", encoding='utf-8') as jsonfile:
        json.dump(rows, jsonfile, indent=2)
    print(f"Converted {csv_path} → {json_path}")

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python csv2json.py input.csv output.json")
    else:
        csv_to_json(sys.argv[1], sys.argv[2])

How it helps

One line in the terminal (python csv2json.py sales.csv sales.json) and you have a perfectly structured JSON array ready for your mock server. I keep this script in a utils repo so any teammate can grab it.

5. Monitor Disk Space and Send Alerts

Why it matters

Nothing is more unsettling than a sudden “disk full” error right before a demo. A tiny watchdog that emails you when usage crosses a threshold can save the day.

The script

import shutil
import smtplib
from email.mime.text import MIMEText

THRESHOLD = 0.85  # 85% usage
ALERT_RECIPIENT = "[email protected]"

def check_disk():
    total, used, free = shutil.disk_usage("/")
    usage = used / total
    return usage

def send_alert(usage):
    body = f"⚠️ Disk usage alert!\nCurrent usage: {usage:.1%}\nConsider cleaning up."
    msg = MIMEText(body)
    msg["Subject"] = "Disk Space Warning"
    msg["From"] = "[email protected]"
    msg["To"] = ALERT_RECIPIENT

    with smtplib.SMTP("smtp.logzly.com", 587) as server:
        server.starttls()
        server.login("[email protected]", "your_app_password")
        server.send_message(msg)
        print("Alert sent.")

if __name__ == "__main__":
    usage = check_disk()
    print(f"Current disk usage: {usage:.1%}")
    if usage > THRESHOLD:
        send_alert(usage)

How it helps

Schedule it with cron to run every hour. If your laptop or server crosses 85 % capacity, you get an email before the system starts whining. I once avoided a catastrophic build failure because the script pinged me at 88 % usage.


Pulling it all together

What ties these five scripts together is a simple philosophy: automate the boring, protect the important. You don’t need a full‑blown orchestration platform for tasks that run once a day or once a week. A few lines of Python, a dash of cron, and you’ve turned repetitive drudgery into a background process you can almost forget about.

A couple of practical tips before you go:

  • Keep your scripts version‑controlled. Even a one‑liner benefits from a commit history when you need to debug later.
  • Store secrets (SMTP passwords, API keys) in environment variables or a .env file—never hard‑code them.
  • Test on a small sample first. A mis‑named file or a changed HTML selector can cause silent failures, and you’ll thank yourself for a quick sanity check.

I’ve been automating my own workflow for the past three years, and the time I’ve reclaimed feels like a small victory each time a script runs without my intervention. Give one of these a spin, tweak it to your own context, and watch the minutes add up to hours.

Reactions