PEP 8 & Style Reference
PEP 8 is Python's official style guide. This page distills the rules that matter most in modern Python 3.14 projects with ruff enforcement.
Search across all documentation pages
PEP 8 is Python's official style guide. This page distills the rules that matter most in modern Python 3.14 projects with ruff enforcement.
[tool.ruff]
line-length = 88
target-version = "py314"
[tool.ruff.lint]
select = ["E", "W", "F", "I"]uv run ruff format . && uv run ruff check --fix .When to reach for this:
| Topic | Rule | Example |
|---|---|---|
| Indentation | 4 spaces, no tabs | def foo(): + 4-space body |
| Line length | 88 chars (Black/ruff default) | Wrap with parentheses |
| Imports | stdlib, third-party, local | Blank line between groups |
| Names | snake_case, CapWords classes | my_function, MyClass |
| Whitespace | space around operators | x = 1, a + b, not x=1 |
| Comments | complete sentences | # Calculate total, not tax. |
| Strings | consistent quote style | double quotes (ruff default) |
# Good PEP 8 style
from __future__ import annotations
import os
from pathlib import Path
import httpx
from pydantic import BaseModel
class Invoice(BaseModel):
id: int
amount: float
customer_email: str
def fetch_invoice(client: httpx.Client, invoice_id: int) -> Invoice:
response = client.get(f"/invoices/{invoice_id}")
response.raise_for_status()
return Invoice.model_validate(response.json())
def main() -> None:
base = os.environ.get("API_URL", "http://localhost:8000")
with httpx.Client(base_url=base) as client:
invoice = fetch_invoice(client, 42)
print(invoice.customer_email)
if __name__ == "__main__":
main()What this demonstrates:
if __name__ guard for script execution| Type | Convention | Example |
|---|---|---|
| Module | lowercase | my_module.py |
| Class | CapWords | InvoiceService |
| Function | snake_case | calculate_total |
| Constant | UPPER_SNAKE | MAX_RETRIES |
| Private | leading _ | _internal_helper |
| Magic methods | dunder | __init__, __str__ |
# Preferred: hanging indent with parentheses
result = some_function(
long_argument_one,
long_argument_two,
long_argument_three,
)
# Dict/list trailing comma ok
settings = {
"host": "localhost",
"port": 8000,
}trailing-whitespace hook.from module import * pollutes namespace. Fix: explicit imports.def f(items=[]): shared state. Fix: None default, create inside.is None, not == None.| Alternative | Use When | Don't Use When |
|---|---|---|
| Google Python style | Google codebase interop | Standard PEP 8 project |
| numpy docstring style | Scientific computing | General web apps |
| Manual formatting | Never | Always use ruff format |
88 is the modern default (Black/ruff). Consistency matters more than the exact number.
Pick one via formatter. ruff format defaults to double quotes.
Generated code, migrations, and rare cases where breaking hurts readability. Document # noqa.
Yes for mechanical rules. Human review still needed for naming quality and structure.
Line too long. Usually ignored when using ruff format.
PEP 484 type hints complement PEP 8. See PEP 484 for typing style.
One blank line between methods in a class. Two blank lines between top-level definitions.
#!/usr/bin/env python3 for executable scripts only.
Not needed in Python 3. UTF-8 is default.
peps.python.org/pep-0008/ - this page is the practical distillation.
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