The Automation Mindset
Decide what to automate — and how to do it safely
In this lesson
Automating a task with Python means writing a small script that does repetitive work for you. Before writing one, it pays to think clearly about what is worth automating and how to do it without causing damage. By the end you’ll frame any chore as inputs, process, and outputs, and you’ll know why every file-changing script should offer a dry run first.
Explain it like I’m 5
Automation is teaching the computer a chore so you don’t repeat the same careful steps by hand. A dry run is the computer telling you what it would do — before it actually does anything.
What automation actually is
Automation means writing a script that does a repetitive, rule-based task for you. The best candidates are chores you do often, that follow clear rules, and that are tedious or error-prone by hand — renaming a batch of photos, cleaning a CSV, building a weekly report. A one-off task you’ll never repeat usually isn’t worth scripting.
# The same chore by hand, then handed to a loop
files = ["report1.txt", "report2.txt", "report3.txt"]
for name in files:
print("Processing", name)
Processing report1.txt Processing report2.txt Processing report3.txt
Inputs, process, outputs
Every useful automation fits one frame: it takes some inputs, runs a process, and produces outputs. Naming those three parts before you code keeps a script focused and makes it far easier to test — the process is usually a plain function you can check on its own.
def clean_names(raw):
return [name.strip().title() for name in raw]
raw = [" ada ", "BO", "cy "]
print(clean_names(raw))
['Ada', 'Bo', 'Cy']
Safety first: dry-run before you touch anything
The moment a script changes real files, a bug can do real damage. The fix is a dry run: instead of acting, the script prints what it would do. You read the plan, confirm it’s right, and only then run it for real. Pair that with a backup and you can automate file changes without fear.
Finish dry_run so it returns a list of strings like "would delete old_1.log" for each file — it must not actually delete anything.
def dry_run(files):
plan = []
for name in files:
pass # TODO: append a "would delete <name>" line
return plan
print(dry_run(["old_1.log", "old_2.log"]))
Inside the loop, build the line with an f-string: plan.append(f"would delete {name}").
def dry_run(files):
plan = []
for name in files:
plan.append(f"would delete {name}")
return plan
print(dry_run(["old_1.log", "old_2.log"]))
['would delete old_1.log', 'would delete old_2.log']
Common mistake: Automating a process you don’t fully understand yet
It’s tempting to script a chore before you’ve done it carefully enough by hand to know all the edge cases.
Do the task manually a few times first and write down the exact rules. Only automate once the process is clear — a script just applies your rules faster, including the wrong ones.
Common mistake: Changing real files with no backup
Early scripts feel small and safe, so it’s easy to point one at important files and run it.
Back up the data first and test on a copy. A five-second backup can save hours of recovery.
Common mistake: Skipping the dry run because “it’ll probably be fine”
Adding a preview mode feels like extra work when you’re sure the script is right.
Build dry-run mode in from the start. Printing the plan costs almost nothing and catches the mistakes you were sure you hadn’t made.
What makes a task a good candidate for automation?
Automation pays off for frequent, rule-based chores — not for one-off or judgement-heavy tasks.
What does a dry run do?
A dry run shows the plan so you can confirm it before anything real happens.
Before a script changes real files, what should you always have?
A backup means a mistake is recoverable; the dry run helps you avoid the mistake in the first place.
Mini exercise (medium)
Write automation_plan(tasks) that takes a list of dicts, each with a name and the minutes spent on it per week, and returns the names of the tasks taking 30 or more minutes a week — the ones worth automating — as a list.
Do it here. Finish the code below and press Run to try your answer right in the browser — no setup needed.
def automation_plan(tasks):
# return the names of tasks taking 30 or more minutes per week
return []
tasks = [
{"name": "rename photos", "minutes": 45},
{"name": "reply to one email", "minutes": 5},
{"name": "build weekly report", "minutes": 60},
]
print(automation_plan(tasks))
Use a list comprehension: [t["name"] for t in tasks if t["minutes"] >= 30].
def automation_plan(tasks):
return [t["name"] for t in tasks if t["minutes"] >= 30]
tasks = [
{"name": "rename photos", "minutes": 45},
{"name": "reply to one email", "minutes": 5},
{"name": "build weekly report", "minutes": 60},
]
print(automation_plan(tasks))
['rename photos', 'build weekly report']
assert automation_plan([{"name": "a", "minutes": 30}]) == ["a"], "30 minutes should qualify (use >= 30)"
assert automation_plan([{"name": "b", "minutes": 10}]) == [], "tasks under 30 minutes should be skipped"
assert automation_plan(tasks) == ["rename photos", "build weekly report"], "pick the 45- and 60-minute tasks"
print("✓ Good automation candidates found!")