Automating Your Life with Python Scripts

The useful threshold is roughly this: if a task takes five minutes and you do it weekly, that is four hours a year. An hour spent scripting it pays back by spring, and the script never gets bored and skips a step.
Start With Files, Because the Feedback Is Instant
pathlib makes filesystem work readable and cross-platform. Handle name collisions from the start, since that is where naive scripts destroy data.
```python
from pathlib import Path
import shutilGROUPS = { 'images': {'.jpg', '.jpeg', '.png', '.webp', '.heic'}, 'docs': {'.pdf', '.docx', '.xlsx', '.csv'}, 'archives': {'.zip', '.tar', '.gz', '.7z'}, }
def tidy(folder: Path, dry_run: bool = True) -> None: for item in folder.iterdir(): if not item.is_file(): continue group = next((g for g, exts in GROUPS.items() if item.suffix.lower() in exts), 'other') target_dir = folder / group target = target_dir / item.name
n = 1 while target.exists(): target = target_dir / f'{item.stem} ({n}){item.suffix}' n += 1
print(f'{item.name} -> {group}/{target.name}') if not dry_run: target_dir.mkdir(exist_ok=True) shutil.move(item, target) ```
Defaulting dry_run to True is the habit that saves you. Watch it print the plan, then pass False.
Scraping Without Being a Nuisance
Check for an API before parsing HTML, since a documented JSON endpoint is stable and a page layout is not. When you must scrape, identify yourself, rate limit, and cache responses locally so development iterations do not hammer someone's server.
```python
import httpx, time
from selectolax.parser import HTMLParserheaders = {'User-Agent': 'personal-price-tracker (contact: me@example.com)'}
with httpx.Client(headers=headers, timeout=15, follow_redirects=True) as client: for url in urls: r = client.get(url) r.raise_for_status() tree = HTMLParser(r.text) node = tree.css_first('[data-testid=price]') print(url, node.text(strip=True) if node else 'not found') time.sleep(2) ```
Make Scripts Survive Contact With Reality
A script that runs unattended needs different qualities from one you babysit.
- Log to a file, not stdout. When it fails at 3am you will want the traceback, not a memory.
- Make it idempotent. Running twice should not double-process anything. Keep a record of what you have already handled.
- Keep secrets in environment variables and never in the file you eventually push to GitHub.
- Add argparse flags for dry runs, paths, and verbosity. Editing constants at the top gets old fast.
- Exit non-zero on failure so your scheduler notices something went wrong.
Scheduling
cron on Linux and macOS, Task Scheduler on Windows, GitHub Actions on a cron trigger when the job needs no local machine. For anything with dependencies between steps, reach for a proper task runner rather than chaining scripts with sleep calls.
Start with the annoyance you complained about most recently. That is the one worth twenty lines.
Enjoyed this article?
Share it with your network and join the conversation.