Standard Library Best Practices
Reach for batteries-included modules before PyPI - and know when stdlib is not enough.
How to Use This List
- Check stdlib during design review before adding dependencies.
- Document escape hatches when PyPI chosen (httpx, pydantic, argon2).
- Pin Python version features to manifest (3.14) in team docs.
A - Selection
- Try pathlib + json + logging before micro-packages. Most scripts need little else.
- Add PyPI when stdlib lacks feature or ergonomics at your scale. HTTP/2, validation, password hashing.
- Prefer tomllib for TOML in 3.11+. Align with pyproject.toml ecosystem and uv 0.6+.
- Use zoneinfo + aware UTC datetimes. Install tzdata on Windows deployments.
- argparse fine for internal CLIs; typer when UX matters. Zero-dep scripts stay argparse.
B - Safety
- subprocess list args, shell=False by default. Audit any shell=True with user input.
- secrets for tokens; never random module. Session and reset links use CSPRNG.
- Never sha256 alone for passwords. argon2/bcrypt via established libraries.
- json.loads untrusted input with size limits. Avoid giant payload DoS.
- re patterns reviewed for catastrophic backtracking. Timeout or simplify pattern.
C - Files & Time
- Path objects and explicit utf-8 encoding on text IO. No string path concat.
- Store UTC; convert with zoneinfo for display. Reject naive datetimes in domain.
- hashlib.file_digest or chunked update for large files. Do not read multi-GB into RAM.
- config precedence: CLI > env > file > defaults. Document order in README.
- No secrets in INI committed to git. Environment injection for keys.
D - Ergonomics
- dataclass + StrEnum for internal DTOs; Pydantic at API edge. Validation boundary clear.
- contextmanager for small scopes; ExitStack for many. Guaranteed teardown.
- itertools lazy chains for large iterables. islice/batched instead of materialize lists.
- functools.lru_cache only on hashable pure functions. No unbounded cache on unbounded args.
- Compile regex at import for hot paths. Named groups for maintainability.
E - Operations
- logging configured in main, not libraries. Libraries use getLogger(name).
- subprocess timeouts on all service calls. No hung children.
- uuid4 for opaque ids; consider uuid7 for DB locality on 3.14+. Match storage type.
- compare_digest for secret comparisons. Timing-safe checks.
- Re-evaluate stdlib each Python upgrade. New batteries (tomllib, batched, uuid7) may remove deps.
FAQs
When is PyPI mandatory?
Production HTTP clients, password hashing, async DB drivers, schema validation at scale.
Is stdlib slower?
Often competitive (hashlib, json); profile before swapping orjson etc.
How to resist dependency bloat?
ADR per new dependency: problem, stdlib alternative rejected, owner, removal criteria.
Windows tzdata?
Add tzdata package to requirements when using zoneinfo.
urllib vs httpx?
urllib ok for tightly controlled scripts; services use httpx with timeouts and pooling.
configparser vs env?
Files for defaults; secrets and per-env overrides in environment variables.
pickle stdlib caution?
Never unpickle untrusted bytes - json or explicit schemas instead.
more-itertools?
Great recipes - but check 3.12+ itertools.batched and stdlib first.
Testing stdlib code?
tmp_path fixture, subprocess mocks, fixed datetimes - deterministic unit tests.
uv and stdlib?
uv manages deps; stdlib ships with Python pin - document both in stack footer.
Related
- Standard Library Overview - module map
- pathlib & os - filesystem
- hashlib, secrets & uuid - crypto hygiene
- Errors & Logging Best Practices - logging policy
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.