Lesson 15 — Files
File Handling
Python file handling uses the with statement for automatic resource management. The csv module and pathlib make common tasks clean and cross-platform.
PYTHON — Writing files
# Writing — "w" creates or overwrites:
with open("attendance.txt", "w") as f:
f.write("Monday: 28 learners present\n")
f.write("Tuesday: 31 learners present\n")
# Appending — "a" adds without erasing:
with open("attendance.txt", "a") as f:
f.write("Wednesday: 27 learners present\n")
# Writing multiple lines at once:
lines = [
"Thursday: 30 learners present",
"Friday: 25 learners present"
]
with open("attendance.txt", "a") as f:
f.writelines(line + "\n" for line in lines)
PYTHON — Reading files
# Reading entire file:
with open("attendance.txt") as f:
content = f.read()
print(content)
# Reading line by line (memory efficient for large files):
with open("attendance.txt") as f:
for line_num, line in enumerate(f, start=1):
print(f"{line_num:3}: {line.strip()}")
# Reading all lines into a list:
with open("attendance.txt") as f:
lines = f.readlines() # includes \n
lines = [line.strip() for line in lines] # remove whitespace
CSV Files
PYTHON — CSV files
import csv
# Writing CSV:
learners = [
["name", "course", "mark"], # header
["Thandi", "Java", 74.5],
["Sipho", "Python", 81.0],
["Lerato", "SQL", 68.0]
]
with open("learners.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerows(learners)
# Reading CSV as dicts (column name → value):
with open("learners.csv") as f:
reader = csv.DictReader(f)
for row in reader:
name = row["name"]
course = row["course"]
mark = float(row["mark"]) # DictReader gives strings
print(f"{name} | {course} | {mark:.1f}%")
pathlib — Modern File Paths
PYTHON — pathlib
from pathlib import Path
# Cross-platform paths (no hardcoded slashes):
data_dir = Path("data")
data_dir.mkdir(exist_ok=True) # create if not exists
log_file = data_dir / "log.txt" # / operator joins paths
log_file.write_text("Started.") # one-line write
print(log_file.read_text()) # one-line read
# File info:
print(log_file.exists()) # True
print(log_file.stat().st_size) # size in bytes
print(log_file.suffix) # .txt
# List all CSV files in a directory:
for csv_path in data_dir.glob("*.csv"):
print(csv_path.name)
Practice Task
Your Turn
Write a LearnerRegistry class that: saves a list of Learner objects to a CSV file with headers, loads them back and reconstructs Learner objects, handles FileNotFoundError with a clear message, handles corrupt/missing fields gracefully. Test by saving 5 learners, clearing the list, reloading, and printing each.
Common Mistakes
- Mode 'w' erases existing content — use 'a' for appending.
- Not stripping newlines when reading —
line.strip()removes leading/trailing whitespace. - Always use
with open()— bareopen()without closing can leak file handles. - Forgetting
newline=''when writing CSV on Windows — causes blank rows. - DictReader gives strings for all values — explicitly convert with int() or float().
Professional Tip
Use pathlib for new code — it is object-oriented, cross-platform, and more readable than os.path. The / operator for path joining is one of Python's cleverest overloads.
Mini Quiz
Which file mode appends to an existing file without erasing it?
'a' opens the file for appending. 'w' creates or truncates. 'r' is read-only. 'x' creates a new file and fails if it already exists.