Files, pathlib, and JSON
Read and write text predictably with context managers, build portable paths with pathlib, and validate JSON data before trusting its shape.
Before this lesson
Manage file resources with with
Construct portable paths using pathlib
Validate parsed JSON structures
The short answer
Use pathlib.Path for paths and with blocks for file lifetimes. Specify text encoding, distinguish missing files from malformed content, and validate decoded JSON because parsing proves syntax—not business correctness.
Build the mental model
Opening a text file creates an operating-system resource. A with statement closes it even when an exception occurs. Path objects join components, inspect existence, and read or write text without manual separator rules.
The central idea in this lesson is persistent boundaries. Read the rule, predict a concrete outcome, and then run the smallest example that can confirm or reject the prediction. This separates knowledge from familiarity with syntax.
Make the design choice explicit
JSON supports objects, arrays, strings, numbers, booleans, and null. json.load returns ordinary Python values. Check expected keys, types, ranges, and version fields before creating domain objects.
import json
from pathlib import Path
path = Path("settings.json")
data = {"theme": "dark", "font_size": 16}
path.write_text(json.dumps(data, indent=2), encoding="utf-8")
loaded = json.loads(path.read_text(encoding="utf-8"))
print(loaded["theme"], loaded["font_size"])
path.unlink()Expected output
dark 16
Trace the example before running it. Identify each input, transformation, returned value, and side effect. Then change one boundary value and explain why the new behavior follows from the rule rather than memorizing the output.
Recognize failure modes
Writing directly over the only good file risks partial data on interruption. For important state, write a temporary file in the same directory and replace atomically. Never deserialize untrusted pickle data.
Use a professional practice loop
Turn the concept into a repeatable workflow: write down the expected behavior, implement one coherent change, run a representative example, and retain a regression check. If the result surprises you, capture the exact input and error before changing anything.
Review the program for names, boundaries, and hidden side effects. A solution is complete when another developer can understand its contract, reproduce its setup, and verify both the successful path and one meaningful failure path.
Quick knowledge check
Answer before you reveal.
01Does successful json.loads prove the data is valid for your application?
No. It proves valid JSON syntax; the application must still validate shape and business rules.
02What four steps make the practice loop reliable?
Predict the behavior, make one coherent change, run it, and retain a check that detects regression.
Exercise
Practice challenge
Save a list of study sessions as versioned JSON, reload it through a validation function, and report helpful errors for missing or malformed files.
Requirements
- The successful path produces the documented result
- At least one boundary or invalid case is handled deliberately
- Calculation or domain logic is separated from console interaction
Optional extension: Add one automated regression check for the most important rule.
Open in Python compilerLesson checkpoint
One small step locks it in
Mark this lesson complete, then keep the momentum going.
Clear up the details
Frequently asked questions
Is persistent boundaries only important in large programs?
No. Small programs reveal the same rules with less noise, and learning the rule early prevents fragile habits from becoming architecture.
Should I memorize every API used here?
No. Memorize the mental model and how to verify behavior. Use documentation for exact names and parameters when needed.
How do I know the exercise is finished?
Meet every success criterion, test at least one boundary or failure case, and explain why the output follows from the code.