Home/Python/Modules, files, and JSON

Modules, files, and JSON

Import reusable code and exchange structured data

Imports

A module is a Python file containing reusable definitions. import json binds the module name; from pathlib import Path imports a named object.

A module's top-level statements normally execute once per interpreter session. Keep prompts and file writes out of import-time code. Put entry-point behavior under if __name__ == "__main__":. A local file named json.py can shadow the standard library module.

Files and JSON

Specify encoding="utf-8" for text files. A with block closes the handle when its scope exits, including after a parsing failure.

JSON objects map to dictionaries, arrays to lists, and null to None. Object keys are strings; integer dictionary keys change type on round trip, and tuples become arrays. Valid JSON syntax does not establish the expected application schema.

Python's encoder accepts non-finite floats by default, though those tokens are outside standard JSON:

Python
import json

payload = {"latency_ms": float("nan")}
print(json.dumps(payload))  # {"latency_ms": NaN}
try:
    json.dumps(payload, allow_nan=False)
except ValueError:
    print("non-finite measurement rejected")
print(json.loads('{"enabled": false}')["enabled"])  # False

allow_nan=False rejects them while encoding. Strict decoding needs its own policy, including parse_constant; field types and ranges still need validation.

Updating an existing file

Opening in "w" mode truncates the destination immediately. Serialize first so a serialization error cannot destroy the previous content:

Python
import json
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as directory:
    destination = Path(directory) / "settings.json"
    destination.write_text('{"version": 1}', encoding="utf-8")
    encoded = json.dumps({"version": 2}, allow_nan=False)
    staged = destination.with_suffix(".tmp")
    staged.write_text(encoded, encoding="utf-8")
    staged.replace(destination)
    print(json.loads(destination.read_text(encoding="utf-8"))["version"])  # 2

This single-writer example stages the file in the same directory, then replaces the destination. Atomic rename, where supported, prevents readers seeing a partial destination. It does not guarantee crash durability or a transaction across multiple files. Concurrent writers also need unique staging names and a conflict policy.

Gotchas

  • Missing files, invalid permissions, malformed text, and invalid application data are different failures. Defaulting after every error can hide a deployment defect.
  • Bound input size; syntactically valid JSON can still consume excessive memory.
  • Do not use eval to parse data. Use a database when updates require queries, concurrency control, or transactions.

Put it into practice

Implement the exercise in a full-screen workspace, then run its tests.

Open practice
Next lessonClasses and objects