Skip to lesson content

PYTHON / LESSON 16 OF 18

Real world automation

Read the explanations, work through the examples, and complete the student tasks.

Learning goals

Combine paths, CSV, logs, backups, and API calls into predictable automation with visible results.

Explanation

Automation follows a small pipeline: read inputs, validate them, process them, and report results. Real scripts also need collision handling, useful logging, and a clear failure policy. The image includes file organization, CSV filtering, log analysis, REST calls, backups, and DevOps workflows. Lesson 15 provides the REST example; the examples here demonstrate the local operations.

Use a new disposable folder for this lesson. Create an inbox folder containing copies of a few .txt and .csv files. Do not point practice code at your only copy of important work.

Example 1 Preview a file organizer

from pathlib import Path
import shutil

root = Path("inbox")
dry_run = True
if not root.is_dir():
    raise FileNotFoundError("Create the practice inbox first")
for source in sorted(root.iterdir()):
    if not source.is_file():
        continue
    group = source.suffix.lower().lstrip(".") or "no_extension"
    target = root / group / source.name
    if target.exists():
        print("SKIP existing:", target)
        continue
    print("PLAN" if dry_run else "MOVE", source, "->", target)
    if not dry_run:
        target.parent.mkdir(exist_ok=True)
        shutil.move(str(source), str(target))

Expected result: planned moves such as inbox/notes.txt to inbox/txt/notes.txt. Files do not move while dry_run is True. After inspecting the plan, setting it to False performs the moves. Existing destinations are skipped. This is a small single-user example; a concurrent production tool needs stronger collision controls.

Example 2 Filter CSV and count log errors

Use students.csv created in Lesson 11, copied into this lesson's folder. Create app.log containing these three lines: INFO Started, ERROR Disk full, ERROR Upload failed.

import csv

with open("students.csv", newline="", encoding="utf-8") as file:
    rows = list(csv.DictReader(file))
selected = [row for row in rows if int(row["score"]) >= 90]
with open("top_students.csv", "w", newline="",
          encoding="utf-8") as file:
    writer = csv.DictWriter(file, fieldnames=["name", "score"])
    writer.writeheader()
    writer.writerows(selected)

with open("app.log", encoding="utf-8") as file:
    errors = [line.rstrip() for line in file
              if line.startswith("ERROR ")]
print("Selected students:", len(selected))
print("Error lines:", len(errors))

Expected output with the stated fixtures: Selected students: 1 and Error lines: 2. top_students.csv contains Sara's record. This example assumes valid scores; a task below adds a malformed-row policy.

Example 3 Create a timestamped backup

from datetime import datetime, timezone
from pathlib import Path
import shutil
import zipfile

source = Path("inbox")
if not source.is_dir():
    raise FileNotFoundError("Create the practice inbox first")
Path("backups").mkdir(exist_ok=True)
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S%fZ")
archive = shutil.make_archive(str(Path("backups") / stamp),
                              "zip", root_dir=source)
with zipfile.ZipFile(archive) as backup:
    print("Archive readable:", backup.testzip() is None)
    print("Entries:", len(backup.namelist()))

The archive is placed outside inbox, preventing it from including itself. The name and entry count vary. A readable ZIP is only an initial check; periodically restore a backup into a separate folder and compare the files.

In DevOps, similar scripts can collect metrics, upload artifacts, invoke container tools, or trigger a build. Use service-specific SDKs and permissions for those operations. Avoid hardcoding credentials; pass configuration through environment variables or an appropriate secret manager.

Student tasks

1. Add a summary of planned, moved, and skipped files to the organizer. Verify a second run does not lose files.

2. Extend CSV processing to report invalid scores with row numbers and continue processing valid rows. Test a blank score and "abc".

3. Count INFO, WARNING, and ERROR records separately in a practice log.

4. Restore the generated ZIP into a separate restore_test folder and compare the restored file contents with the originals.

Completion check: submit the inputs, an execution log, and evidence that the backup can be restored.