50 Python Rules Every Specialist Should Follow
A master checklist of habits that separate production Python from tutorial code. Grouped by domain; every rule is actionable and enforceable with tooling where noted.
Search across all documentation pages
A master checklist of habits that separate production Python from tutorial code. Grouped by domain; every rule is actionable and enforceable with tooling where noted.
Scan this list quarterly. Enable ruff/mypy rules that automate each "enforceable" item.
When to reach for this:
| # | Rule | Category |
|---|---|---|
| 1-10 | Style & readability | Formatting |
| 11-20 | Types & contracts | Safety |
| 21-30 | Structure & modules | Design |
| 31-40 | Errors & testing | Reliability |
| 41-50 | Security & ops | Production |
invoice_total, not x or tmp.f"{name}" over "{}".format() and % formatting.if foo: bar().pathlib.Path - not os.path.join for new code.enum.Enum - for fixed sets of constants, not string literals.X | None, not Optional[X] - Python 3.14 union syntax.list[str] over List[str] - builtin generics (PEP 585).TypedDict or Pydantic - for structured dicts, not bare dict.isinstance - not bare type() checks.Protocol for duck typing - structural subtyping over ABCs when appropriate.# type: ignore needs a reason.frozen=True when immutable.TYPE_CHECKING lazy imports.from myapp.services import billing, not relative dot chains in libraries.__all__ - for package public API surface.__init__.py - re-exports only; keep it thin.pyproject.toml - single config for deps, tools, and build.raise ValueError("pct must be 0-100"), not bare raise Exception.except: pass is almost always wrong.raise NewError(...) from original.with open(...) and @contextmanager.test_discount_over_100_raises.print in libraries - use logging with module-level logger..env gitignored.uv sync --frozen in CI.secrets module - not random for tokens and passwords.pip-audit in CI - weekly dependency vulnerability scan.| Alternative | Use When | Don't Use When |
|---|---|---|
| Team style guide doc | Custom conventions beyond PEP 8 | Rules already covered here |
| Ruff rule codes only | Automation-focused team | Onboarding needs rationale |
| Linter without list | Small experienced team | Growing team needs shared baseline |
Map to ruff select rules, mypy strict, pre-commit hooks, and CI required checks.
Types (11-20), testing (31-40), and security (41-50) prevent production incidents.
Scripts relax 21-30 (structure) but keep security (41-50) and style (1-10).
Quarterly team review. Update when Python or tooling releases major versions.
Security and correctness beat style. Document trade-offs in PR description.
Juniors: focus 1-20 first. Seniors: enforce 41-50 in review and architecture.
Rules 1-10 expand PEP 8 with modern tooling (ruff, pathlib, f-strings).
No. Universal Python. See 40 API rules for web-specific guidance.
Use as CI policy doc. ruff.toml and mypy.ini are the machine-readable form.
See 30 Async Rules for asyncio-specific rules.
Stack versions: This page was written for Python 3.14.0, 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+.
Reviewed by Chris St. John·Last updated Jul 19, 2026