Most developers think they understand automation.
They don’t.
They schedule things. They glue scripts together. They feel productive because something runs “every 10 minutes.”
That’s not automation. That’s outsourcing boredom to a clock.
Real automation has three properties:
- It observes
- It decides
- It acts
And most importantly — it survives without you.
Below are 7 Python projects that force you to cross that line. They look small. They aren’t. Each one rewires how you think about systems.
1. The Script That Refuses to Die
If your automation crashes silently, it’s not automation. It’s a liability.
Build a runner that doesn’t just restart a script — it understands failure patterns.
import subprocess
import time
from collections import deque
FAIL_WINDOW = 300 # seconds
MAX_FAILS = 3
failures = deque()
def run_worker():
return subprocess.run(
["python", "worker.py"],
capture_output=True
)
while True:
result = run_worker()
if result.returncode != 0:
now = time.time()
failures.append(now)
# keep only recent failures
while failures and now - failures[0] > FAIL_WINDOW:
failures.popleft()
if len(failures) >= MAX_FAILS:
print("Too many failures. Escalating.")
break
else:
print("Failure detected. Retrying...")
time.sleep(3)
Pro tip: “Retries don’t fix bugs. They hide them long enough to become outages.”
2. The System That Understands User Intent
Most file watchers are reactive.
File changed? Trigger something.
That’s primitive.
Instead, detect *patterns
import os
import time
def snapshot(folder):
return {
f: os.stat(os.path.join(folder, f)).st_mtime
for f in os.listdir(folder)
}
previous = snapshot("workspace")
while True:
time.sleep(2)
current = snapshot("workspace")
changed = [
f for f in current
if f in previous and current[f] != previous[f]
]
if len(changed) > 5:
print("Bulk operation detected → switch to batch processing")
elif len(changed) == 1:
print("Single file edit → real-time processing")
previous = current
Good automation doesn’t react fast. It reacts correctly.
3. The Backup System That Doesn’t Panic
Most backups are paranoid.
They copy everything. Every time.
Instead, detect meaningful change.
import difflib
from pathlib import Path
def meaningful_change(old, new, threshold=0.98):
ratio = difflib.SequenceMatcher(None, old, new).ratio()
return ratio < threshold
source = Path("docs")
backup_dir = Path("backup")
backup_dir.mkdir(exist_ok=True)
for file in source.glob("*.txt"):
backup = backup_dir / file.name
if backup.exists():
old = backup.read_text()
new = file.read_text()
if meaningful_change(old, new):
print(f"Updating backup: {file.name}")
backup.write_text(new)
else:
print(f"Creating backup: {file.name}")
backup.write_text(file.read_text())
Real systems don’t store data. They store meaningful change.
4. The Automation That Says “Not Now”
This one sounds simple until you try it.
import psutil
import time
def system_ready():
cpu_ok = psutil.cpu_percent(interval=1) < 50
mem_ok = psutil.virtual_memory().percent < 75
return cpu_ok and mem_ok
while True:
if system_ready():
print("System stable → running heavy task")
break
else:
print("System busy → waiting...")
time.sleep(5)
Quote: “The fastest system is the one that knows when to stay idle.”
5. The “Dumb” Anomaly Detector That Actually Works
No ML. Just baselines.
from collections import Counter
baseline = Counter()
# build baseline
with open("logs.txt") as f:
for line in f:
event = line.split()[0]
baseline[event] += 1
def detect(line):
event = line.split()[0]
if baseline[event] < 3:
print("⚠ Rare event detected:", line.strip())
# monitor new logs
with open("new_logs.txt") as f:
for line in f:
detect(line)
If your system alerts constantly, it’s broken. If it alerts rarely but accurately, it’s trusted.
6. The Scheduler That Understands Time Decay
FIFO is comfortable. It’s also wrong.
import heapq
import time
tasks = []
def add_task(name, delay_seconds):
deadline = time.time() + delay_seconds
heapq.heappush(tasks, (deadline, name))
add_task("send_otp", 30)
add_task("cleanup", 3600)
add_task("email_report", 120)
while tasks:
deadline, task = heapq.heappop(tasks)
if time.time() > deadline:
print(f"Skipping expired task: {task}")
else:
print(f"Running task: {task}")
Time changes the value of work. Your automation should reflect that.
7. The System That Explains Its Own Decisions
Logs tell you what happened.
You need why.
def decision(reason, action):
print(f"[WHY] {reason}")
print(f"[ACTION] {action}")
disk_free_gb = 8
if disk_free_gb < 10:
decision(
"Disk space below safe threshold",
"Triggering cleanup process"
)
else:
decision(
"Disk space sufficient",
"No action needed"
)
Comments
Loading comments…