Most automation tutorials show you how to scrape a website or sort files alphabetically. That is not automation. That is procrastination with a script. Real automation is identifying repetitive tasks that cost you real time and eliminating them permanently. Here is the framework I use. ## The 5-Minute Rule If a task takes more than 5 minutes and you do it more than twice a week, automate it. Calculate the math: ``` Time saved per week = (minutes per task) × (frequency per week) Time to write script = typically 30–90 minutes for simple tasks ROI threshold = breakeven in 2 weeks ``` If the math works, build it. ## Category 1: File & Folder Management The most common time sink. Renaming files, organizing downloads, converting formats. ```python import os import shutil from pathlib import Path # Auto-organize Downloads folder by file type DOWNLOADS = Path.home() / "Downloads" FOLDERS = { "Images": [".jpg", ".jpeg", ".png", ".gif", ".webp"], "Documents": [".pdf", ".docx", ".txt", ".xlsx"], "Videos": [".mp4", ".mkv", ".mov", ".avi"], "Archives": [".zip", ".rar", ".7z", ".tar"], } for file in DOWNLOADS.iterdir(): if file.is_file(): ext = file.suffix.lower() for folder, extensions in FOLDERS.items(): if ext in extensions: dest = DOWNLOADS / folder dest.mkdir(exist_ok=True) shutil.move(str(file), str(dest / file.name)) print(f"Moved {file.name} → {folder}/") ``` Run this once manually. Then schedule it with Windows Task Scheduler or Linux cron. ## Category 2: Repetitive Web Tasks (Without APIs) Some sites do not have APIs. Selenium and Playwright fill the gap. ```python from playwright.sync_api import sync_playwright def fill_daily_report_form(data: dict): with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto("https://internal-portal.example.com/daily-report") page.fill("#field-name", data["name"]) page.fill("#field-tasks", data["tasks"]) page.select_option("#field-status", data["status"]) page.click('button[type="submit"]') page.wait_for_selector(".success-message") print("Report submitted successfully") browser.close() ``` I use this pattern for internal portals that update their layout frequently — Playwright is more resilient to minor UI changes than raw Selenium. ## Category 3: Data Aggregation & Reports Pulling data from multiple sources, combining it, sending a summary. ```python import requests import smtplib from email.mime.text import MIMEText from datetime import datetime def send_daily_github_summary(username: str, token: str, email: str): headers = {"Authorization": f"token {token}"} # Get today's commits events = requests.get( f"https://api.github.com/users/{username}/events", headers=headers ).json() today = datetime.now().date().isoformat() commits = [ e for e in events if e["type"] == "PushEvent" and e["created_at"][:10] == today ] summary = f"GitHub Summary for {today}\n\n" for c in commits: repo = c["repo"]["name"] count = len(c["payload"]["commits"]) summary += f"• {repo}: {count} commit(s)\n" if not commits: summary += "No commits today." msg = MIMEText(summary) msg["Subject"] = f"Daily GitHub Summary — {today}" msg["From"] = email msg["To"] = email with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server: server.login(email, "your-app-password") server.send_message(msg) print("Summary sent!") ``` ## Category 4: Android + Python Bridge Since I build Android apps at AshuTech, I frequently use Python to automate testing and device management. ```python import subprocess def install_and_launch(apk_path: str, package: str, activity: str): # Install APK on connected device via ADB subprocess.run(["adb", "install", "-r", apk_path], check=True) # Launch the app subprocess.run([ "adb", "shell", "am", "start", "-n", f"{package}/{activity}" ], check=True) print(f"Installed and launched {package}") def capture_screenshot(output_path: str): subprocess.run(["adb", "shell", "screencap", "/sdcard/screen.png"]) subprocess.run(["adb", "pull", "/sdcard/screen.png", output_path]) print(f"Screenshot saved to {output_path}") ``` This pattern lets me automate the full build-install-screenshot-test loop without touching the device manually. ## Building Scripts That Last The biggest failure mode: you build a script that works once, then it breaks and you never fix it. Prevention: 1. **Add logging** — every script should write to a log file 2. **Handle errors explicitly** — catch expected failures, re-raise unexpected ones 3. **Test with bad input** — what happens when the file doesn't exist? When the API returns 429? 4. **Document it** — a one-paragraph comment at the top saves future-you hours ```python import logging logging.basicConfig( filename="automation.log", level=logging.INFO, format="%(asctime)s — %(levelname)s — %(message)s" ) def my_script(): logging.info("Script started") try: # your code logging.info("Script completed successfully") except FileNotFoundError as e: logging.error(f"Input file missing: {e}") raise except Exception as e: logging.critical(f"Unexpected error: {e}", exc_info=True) raise ``` ## Where to Start Pick the most annoying repetitive task you did this week. Time yourself doing it manually. Now write a Python script that does it. Run it. Compare the time. You will never go back. --- *Ashu Anand — Founder, AshuTech | Building automation and Android tools at [ashutech.xyz](https://www.ashutech.xyz)*
Back to all articles
Automating the Repetitive: Python Scripts That Actually Save Time
How to identify automation opportunities in your workflow and build tools that actually save time — not just scripts that look impressive but sit unused.

View all articles