What you'll learn
Programs become useful when they read and write real data — config files, logs, exports, datasets. Python makes file I/O simple and safe, especially with the with statement and the modern pathlib module. We'll finish with the two formats you'll use constantly: CSV and JSON.
By the end you'll be able to:
- Read and write files safely with
with open() - Choose the right file mode and encoding
- Manipulate paths with
pathlib - Work with CSV and JSON files
open() & the with statement
open() returns a file object; the with statement guarantees it's closed automatically when the block ends — even if an error occurs. Always use with; forgetting to close files leaks resources and can lose unwritten data:
# Write, then read back — the with statement closes the file automatically.
with open("notes.txt", "w", encoding="utf-8") as f:
f.write("Line one\n")
f.write("Line two\n")
with open("notes.txt", "r", encoding="utf-8") as f:
for line in f: # iterate lines lazily
print(line.strip())Tip
for line in f) reads one line at a time rather than loading the whole file into memory. This lets you process gigabyte-sized files with a tiny memory footprint — a first taste of the lazy processing we'll deepen with generators.Modes & encodings
The second argument to open() is the mode:
"r"read (default),"w"write (truncates!),"a"append,"x"create-only.- Add
"b"for binary (images, etc.), e.g."rb".
Always pass encoding="utf-8" for text files. Relying on the platform default is a classic source of "works on my machine" bugs where accented characters break on another OS.
Watch out
"w" mode erases the file's existing contents the moment you open it. Reach for "a" (append) when you want to add without destroying, and "x" when you want it to fail rather than overwrite an existing file.Paths with pathlib
The modern pathlib module treats paths as objects. Join them with the / operator (correct on every OS), and get parts, check existence, or search with glob — far cleaner than gluing strings together:
from pathlib import Path
p = Path("data") / "reports" / "june.txt" # OS-correct joining with /
print(p.name) # june.txt
print(p.suffix) # .txt
print(p.parent) # data/reports
here = Path(".")
for txt in here.glob("*.py"): # find files by pattern
print(txt)CSV & JSON
JSON is the lingua franca of the web and configs — json.dump/json.load convert between Python objects and JSON text (dicts ↔ objects, lists ↔ arrays):
import json
data = {"name": "Ada", "skills": ["Python", "math"], "active": True}
# Object -> JSON file
with open("user.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
# JSON file -> object
with open("user.json", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded["skills"])
print(json.dumps(loaded)) # to a stringCSV is the spreadsheet-friendly format for tabular data. The csv module handles the quoting and commas for you — DictReader even gives you each row as a dict keyed by the header:
import csv
rows = [["name", "score"], ["Ada", 95], ["Alan", 88]]
with open("scores.csv", "w", newline="", encoding="utf-8") as f:
csv.writer(f).writerows(rows)
with open("scores.csv", newline="", encoding="utf-8") as f:
for row in csv.DictReader(f): # reads rows as dicts
print(row["name"], row["score"])Recap & quick check
Key takeaways
- Always use with open(...) so files close automatically, even on error.
- Iterating a file reads line by line — memory-efficient for huge files.
- Modes: r read, w write (truncates!), a append, x create-only; add b for binary. Pass encoding='utf-8'.
- pathlib treats paths as objects: join with /, and use .name/.suffix/.parent and glob().
- json.dump/load handle JSON; the csv module (and DictReader) handle tabular CSV data.
Quick check
1. Why use 'with open(...)' instead of a plain open()?
2. What does opening a file in 'w' mode do to existing contents?
3. How do you join paths portably with pathlib?
4. Which functions convert between Python objects and a JSON file?
5. Why iterate a file with 'for line in f'?
Speaking of memory-efficient, lazy processing — that's exactly what's next. Module 22 — Iterators & Generators.