Skip to content
← DevOps foundations

Learning bite

Files and configuration

Read a small configuration file and reject invalid values before acting.

Documentation reviewed2026-10-01 · 3 min read
On this page

A configuration file is input, not trusted code

Configuration lets the same program operate on different values without editing its source. A file can be readable yet contain invalid syntax; valid JSON can still have missing fields or impossible values. Check those layers separately so a failure tells the caller what to fix.

In the existing capacity-tool directory, save capacity.json beside capacity.py:

json
{"total": 20, "used": 8}

JSON objects become Python dictionaries, arrays become lists, and JSON null becomes None. Save read_capacity.py:

python
import json
from pathlib import Path
from capacity import remaining_gib

def read_capacity(path: Path) -> int:
    data = json.loads(path.read_text(encoding="utf-8"))
    if not isinstance(data, dict) or set(data) != {"total", "used"}:
        raise ValueError("expected exactly total and used fields")
    return remaining_gib(data["total"], data["used"])

if __name__ == "__main__":
    print(read_capacity(Path("capacity.json")))

Run python read_capacity.py from the project root. Expected output: 12. Path represents a filesystem path. read_text reads bytes and decodes UTF-8; json.loads turns JSON text into Python values. Checking the exact key set catches both missing fields and typos such as uesd. The imported function performs the numeric checks.

Diagnose one layer at a time

Save a copy of the valid fixture before these trials. Restore it between trials.

ChangeExpected failureWhat it tells you
Rename capacity.jsonFileNotFoundErrorThe path does not identify a readable file here.
Remove a closing braceJSONDecodeErrorThe contents are not valid JSON.
Add "extra": 1ValueError from our schema checkValid JSON does not match this tool's fields.
Change used to 25ValueError from remaining_gibThe values violate our capacity rule.
Change used to "8"TypeErrorThe tool requires a number, not numeric text.

The uncaught traceback is useful while learning. The next lesson converts these expected failures into a concise CLI error and a nonzero exit status.

Decide how files are located and values are chosen

Relative paths start from the process's current working directory. Running /somewhere/capacity-tool/read_capacity.py from another folder does not move the process there. An explicit configuration argument makes that choice visible.

Python 3.11 includes tomllib for reading TOML. YAML needs an additional library; use its safe data-loading interface, not an arbitrary object loader. Do not use eval to read configuration. The format changes the parser, but the need to validate types and meaning remains.

If a tool has defaults, a file, environment values, and CLI flags, document a winning order. For example, with default timeout 3, file 5, environment 8, and CLI 10, a defaults→file→environment→CLI rule produces 10. Convert and validate the winning value; environment values arrive as strings. Avoid silently treating an invalid override as a reason to use a default.

Writing deserves its own decision. Directly overwriting a live file can leave partial contents if interrupted. A common approach writes a temporary file in the destination directory, validates it, then replaces the destination. Permissions, concurrent writers, and durability still matter; the reporting tool here does not need to write configuration at all.

Checkpoint

Why not accept unknown fields automatically? A misspelling could quietly change behavior. A more extensible format can allow extras deliberately, but this small format promises exactly two fields. Can a valid parser prove used <= total? No; that is a rule of our program.

Restore the valid fixture and retain both Python modules. Next, expose their behavior through arguments, stdout, stderr, and exit codes.

References: pathlib↗, JSON↗, TOML↗, and os.replace↗.

Your notes and evidence

Record observations, questions, or links to your work. Keep credentials out of your notes.

Loading saved progress…

Back up or restore this path

Progress and notes stay in this browser. A backup contains only this learning path.