Skip to main content

Python Engineering Guide

Modern Python development is about more than just writing code; it's about building reproducible, maintainable, and high-performance systems. This guide focuses on the modern Astral (uv/Ruff) stack.

The Modern Stack (2024+)

We recommend a unified toolchain to minimize "tool sprawl" and maximize performance.

CategoryToolWhy?
Package Manageruv10-100x faster than pip/poetry; unified venv/python manager.
Linter/FormatterRuffReplaces Flake8, Black, isort, and Bandit with a single Rust-based tool.
Type CheckerMyPyIndustry standard for static type analysis.
TestingpytestFeature-rich, modular testing framework.
Configpyproject.tomlThe single source of truth for project metadata and tool config.

Project Structure

A standardized layout ensures team members and tools can navigate the codebase easily.

project-name/
├── pyproject.toml # Configuration (The heart of the project)
├── uv.lock # Deterministic lockfile (Commit this!)
├── .python-version # Pinned Python version (e.g., 3.12)
├── src/ # Source code (using src-layout)
│ └── my_package/
│ ├── __init__.py
│ └── main.py
├── tests/ # Test suite
│ ├── conftest.py
│ └── test_main.py
└── .github/ # CI/CD workflows
└── workflows/ci.yml

Dependency Management with uv

uv is a drop-in replacement for pip, pip-tools, and poetry.

Core Workflow

# Initialize a new project
uv init --lib

# Add dependencies
uv add requests fastapi
uv add --dev pytest ruff mypy

# Sync environment with lockfile
uv sync
Lockfiles

Always commit uv.lock. It ensures every developer and CI runner uses the exact same versions of every dependency, including transitive ones.


Code Quality (Ruff & MyPy)

Ruff Configuration

Ruff replaces Flake8, isort, Black, and Bandit with a single, extremely fast tool. Consolidate all rules in pyproject.toml:

[tool.ruff]
line-length = 88
target-version = "py312"

[tool.ruff.lint]
select = [
"E", "F", "W", # Default flake8
"I", # isort (import sorting)
"UP", # pyupgrade
"S", # bandit (security)
"B", # bugbear
]

# Import-specific configuration
[tool.ruff.lint.isort]
known-first-party = ["my_package"]
force-sort-within-sections = true # Sort within import groups
combine-as-imports = true # Merge: from x import a; from x import b -> from x import a, b
lines-after-imports = 2 # PEP 8 standard
Import Rules

The "I" rule enables automatic import sorting (replaces isort):

  • Groups: stdlib → third-party → local
  • Sorts alphabetically within groups
  • Detects unused imports (F401)
  • Flags from module import * (F403)

Type Checking

Use MyPy to catch logic errors before they reach production:

uv run mypy src/

Continuous Integration (GitHub Actions)

Automate your quality gates. A typical ci.yml using setup-uv:

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v3
- name: Install & Check
run: |
uv sync
uv run ruff check .
uv run mypy src/
uv run pytest


Code Organization

Python Import System

Understanding Python's import mechanism is crucial for building scalable applications. Key concepts include:

  • Absolute vs Relative Imports: Use absolute imports for clarity, relative imports within packages
  • __init__.py: Control package-level API and initialization
  • Avoiding Circular Imports: Use TYPE_CHECKING or refactor dependencies
  • Import Performance: Consider lazy imports for heavy dependencies
# ✅ Recommended: Absolute imports
from my_package.utils import load_config
from my_package.core import Engine

# ✅ Acceptable: Explicit relative imports
from .utils import load_config
from ..core import Engine
tip

Configure Ruff to enforce PEP 8 import ordering and detect circular dependencies automatically.


Engineering Resources