0% found this document useful (0 votes)
2 views14 pages

Python Best Practices Guide

Uploaded by

kisszhanghao
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views14 pages

Python Best Practices Guide

Uploaded by

kisszhanghao
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Python Programming Best Practices Guide

Version: 3.0 | Updated: July 2026


Audience: Intermediate to Advanced Python Developers

This guide consolidates proven Python programming best practices drawn from years of production experience across hundreds
1. Coding Style and Conventions

1.1 PEP 8 Compliance:


PEP 8 is the official style guide for Python. Key rules: 4 spaces for indentation (never tabs), limit lines to 79 chars for code and 7

1.2 Naming Conventions:


- Functions and variables: snake_case (e.g., calculate_total, user_email)
- Classes: PascalCase (e.g., UserRepository, PaymentProcessor)
- Constants: UPPER_SNAKE_CASE (e.g., MAX_RETRY_COUNT)
- Private members: prefix with single underscore (e.g., _internal_cache)

1.3 Code Formatting Tools:


- Black: Opinionated formatter with zero configuration; use as pre-commit hook
- isort: Automatically sorts and organizes imports
- flake8: Linter for PEP 8 compliance and common errors
- mypy: Static type checker catching type bugs before runtime
2. Type Hints and Static Analysis

2.1 Why Type Hints Matter:


Type hints (Python 3.5+, improved through 3.12) provide function signature and variable type annotations. Benefits: improved ID

2.2 Best Practices:


- Annotate all public function signatures with parameter and return types
- Use Optional[T] or T | None (3.10+) for optional parameters
- Prefer abstract types (Sequence, Mapping, Iterable) over concrete (list, dict) for parameters
- Use Protocol classes for structural subtyping
- Leverage TypedDict for known-schema dictionaries
- Use Literal types to constrain values to specific sets
3. Project Structure and Organization

3.1 Recommended Layout:


project-name/
src/package_name/
__init__.py | [Link] | [Link] | [Link] | [Link]
tests/test_core.py | test_models.py | [Link]
docs/ | [Link] | [Link] | [Link]

3.2 Key Principles:


- Use src-layout to prevent accidental package import from source tree during testing
- Keep configuration in [Link] (PEP 621) rather than [Link] or [Link]
- Separate business logic from I/O boundaries for testability
- Use dependency injection over global state and singletons
- Organize by feature/domain rather than technical layer for larger projects

3.3 Package Management:


- Virtual environments for isolation (venv)
- Pin dependencies with exact versions; use Poetry/Pipenv for lock files
- Separate dev dependencies from production
- Consider Docker for development environment consistency
4. Error Handling and Logging

4.1 Exception Handling:


- Catch specific exceptions rather than bare except clauses
- Never silently swallow exceptions; at minimum, log them
- Use exception chaining (raise ... from ...) to preserve context
- Define custom exception hierarchies for your application domain
- Avoid exceptions for control flow in performance-critical paths

4.2 Custom Exception Hierarchy:


class AppError(Exception): pass # Base exception for all application errors.
class ValidationError(AppError): pass # Raised when input validation fails.
class ResourceNotFoundError(AppError): pass # Raised when resource not found.

4.3 Logging Configuration:


- Use standard logging module; avoid print() for diagnostics
- Configure log levels per environment: DEBUG (dev), INFO (staging), WARNING (prod)
- Structured logging with structlog or python-json-logger
- Log rotation to prevent disk space exhaustion
- Redact sensitive info (passwords, tokens, PII) before logging

4.4 Log Levels:


DEBUG: Detailed diagnostics | INFO: Normal operation | WARNING: Unexpected non-blocking | ERROR: Operation failure | CR
5. Testing Strategies

5.1 Testing Pyramid:


- Unit Tests (70% of suite): Test individual functions/methods in isolation. Use pytest, aim for under 100ms per test.
- Integration Tests (20%): Test component interactions (DB, APIs, filesystem). Use fixtures and factories.
- End-to-End Tests (10%): Complete user workflows. Use Playwright or Selenium.

5.2 Best Practices:


- Follow Arrange-Act-Assert (AAA) pattern
- Write tests before fixing bugs to validate the fix
- Use parametrized tests for multiple input combinations
- Mock external dependencies but avoid over-mocking
- Keep tests deterministic; no dependency on external state or network
- Target fast suites: full test run under 5 minutes

5.3 Code Coverage:


- Target 90%+ line coverage for critical business logic
- 100% branch coverage for security-sensitive paths
- Use [Link] with pytest-cov integration
- Coverage is a tool to find untested code, not a goal in itself
6. Performance Optimization

6.1 Measure Before Optimizing:


Profile first using cProfile, py-spy, or line_profiler. Focus on the 20% of code that accounts for 80% of execution time.

6.2 Common Techniques:


- Use built-in functions and stdlib (written in C) over pure Python
- List comprehensions and generator expressions for data processing
- [Link] for queue ops instead of [Link](0)
- Sets and dicts for O(1) membership testing over O(n) list scanning
- functools.lru_cache or [Link] for expensive computations
- __slots__ to reduce memory for classes with many instances

6.3 Concurrency and Parallelism:


- asyncio: I/O-bound workloads with thousands of concurrent connections
- ThreadPoolExecutor: I/O-bound with moderate concurrency
- ProcessPoolExecutor: CPU-bound parallel computation
- Avoid GIL limitations via multiprocessing or subinterpreters (3.12+)
- Consider async/await for web servers, API clients, database operations

6.4 Database Optimization:


- Connection pooling (SQLAlchemy pool, asyncpg pool)
- Eager loading to avoid N+1 query problems
- Appropriate indexes based on query patterns
- Batch operations for large datasets
- Monitor slow queries (pg_stat_statements, EXPLAIN ANALYZE)
7. Security Best Practices

7.1 Input Validation:


- Never trust user input; validate at application boundaries
- Use Pydantic or Marshmallow for declarative validation
- Escape output to prevent injection (XSS, SQL, command)
- Apply principle of least privilege for all operations

7.2 Authentication and Authorization:


- Use established libraries (python-jose, PyJWT) for JWT handling
- Multi-factor authentication for sensitive operations
- bcrypt or argon2 for password hashing; never store plain-text
- Rate limiting on auth endpoints to prevent brute force
- Secure session management: secure, httpOnly, SameSite cookies

7.3 Dependency Security:


- Audit dependencies with pip-audit, safety, or Snyk
- Pin versions and use hash-checking mode
- Monitor CVE and PyPA advisory databases
- Automate updates with Dependabot or Renovate
- Maintain SBOM for compliance

7.4 Secrets Management:


- Never hardcode secrets in source code
- Use env vars or secrets manager (Vault, AWS Secrets Manager)
- Rotate secrets regularly and on suspected compromise
- .gitignore for .env files
- Secret scanning in CI/CD (git-secrets, truffleHog)
8. Documentation and API Design

8.1 Code Documentation:


- Docstrings for all public modules, classes, functions (PEP 257)
- Google-style or NumPy-style for consistency
- Document parameters, returns, exceptions, and usage examples
- Comments focus on why, not what; code should be self-documenting
- Auto-generate API docs with Sphinx, MkDocs, or pdoc

8.2 API Design:


- RESTful: Follow OpenAPI/Swagger spec. Use FastAPI for automatic docs.
- GraphQL: Use Strawberry or Graphene with clear schema descriptions.
- gRPC: Protobuf definitions as source of truth for service contracts.
- Library APIs: Principle of least astonishment; make simple things simple.

8.3 Versioning:
- Semantic versioning (SemVer) for libraries: [Link]
- API versioning via URL path (/v1/, /v2/) or Accept header
- Maintain [Link] with clear upgrade notes
- Deprecate with warnings and migration paths before removal
- Support at least one previous major version during transition
9. Modern Python Tooling (2026 Edition)

9.1 Essential Tools:


- Ruff: Blazing-fast linter and formatter in Rust. Replaces flake8, isort, and dozens of plugins with 10-100x speedup. De facto sta
- uv: Fast package installer and resolver in Rust. Replaces pip, pip-tools, virtualenv. 10-100x faster dependency resolution.
- [Link]: Unified project config (PEP 621). Consolidates [Link], [Link], [Link], [Link], .flake8, [Link].

9.2 Testing and Quality:


- pytest 8.x: Standard framework with powerful fixtures and plugins
- [Link]: Coverage measurement with branch support
- Hypothesis: Property-based testing generating cases from specifications
- Playwright: Modern browser automation for E2E testing

9.3 CI/CD:
- GitHub Actions or GitLab CI for automated pipelines
- Docker multi-stage builds for optimized images
- pre-commit hooks for automated quality checks
- tox or nox for multi-version testing
10. Asynchronous Programming Patterns

10.1 Async/Await Fundamentals:


Python asyncio ecosystem is mature. Key patterns: async context managers (async with) for resource lifecycle, async iterators (

10.2 Common Patterns:


- Producer-Consumer: [Link] with backpressure handling
- Circuit Breaker: Prevent cascading failures by detecting unavailability
- Retry with Exponential Backoff: tenacity or stamina for resilient operations
- Background Tasks: asyncio.create_task() with proper error handling
- Graceful Shutdown: Handle SIGTERM/SIGINT to drain in-flight requests

10.3 Pitfalls to Avoid:


- Blocking the event loop with CPU-bound or sync I/O
- Creating tasks without retaining references (GC can cancel them)
- Mixing sync and async without proper boundaries (use asyncio.to_thread())
- Forgetting to close connections and sessions (resource leaks)
- Assuming ordered execution with [Link]()
11. Database Interactions and ORM Usage

11.1 Choosing the Right Tool:


- SQLAlchemy 2.0+: Most mature ORM. Use 2.0-style API with select() and explicit sessions. Supports Core (low-level SQL) an
- Django ORM: Tightly integrated; suitable for Django projects.
- Peewee: Lightweight ORM for smaller projects.
- asyncpg: High-performance async PostgreSQL driver. Use with SQLAlchemy async or standalone.

11.2 Best Practices:


- Use migrations (Alembic, Django migrations) for all schema changes
- Repository pattern to abstract data access behind interfaces
- Unit of Work pattern for coordinating multi-repository transactions
- Avoid N+1 queries: selectinload() or joinedload() for eager loading
- Appropriate isolation levels based on consistency needs
- Connection pooling: 5-20 connections per worker
- Monitor query performance with Django Debug Toolbar or sqlalchemy-logging
12. Deployment and Production Operations

12.1 Containerization:
- Multi-stage Docker builds to minimize image size (under 200MB)
- Run as non-root user inside containers for security
- .dockerignore to exclude unnecessary files
- Resource limits (CPU, memory) in orchestration
- Health check endpoints for orchestration platforms

12.2 Web Servers:


- Gunicorn with uvicorn workers for ASGI (FastAPI, Starlette, Django)
- Workers: (2 x CPU cores) + 1 as starting point
- Nginx or Caddy as reverse proxy for TLS, static files, load balancing
- Graceful shutdown with pre-stop hooks in Kubernetes

12.3 Observability:
- Structured logging: structlog with correlation IDs for request tracing
- Metrics: Prometheus client. Track latency, error rates, business KPIs.
- Tracing: OpenTelemetry for distributed tracing across microservices
- Error tracking: Sentry or similar for real-time alerting
- Health checks: Liveness and readiness probes for orchestration

12.4 Continuous Deployment:


- Blue-green or canary deployments for zero-downtime
- Feature flags decouple deployment from release (LaunchDarkly or open-source)
- Backward-compatible DB migrations; never deploy breaking schema changes with code
- Maintain runbooks for operational procedures and incident response
13. Appendix: Recommended Resources

Books:
- Fluent Python (2nd Ed.) by Luciano Ramalho - definitive guide to advanced Python
- Architecture Patterns with Python by Percival and Gregory - DDD and event-driven architecture
- Robust Python by Patrick Viafore - Type-driven development for maintainable codebases
- CPython Internals by Anthony Shaw - Understanding Python runtime

Online:
- PEPs: [Link]
- PyPA: [Link]
- Real Python: [Link] - In-depth tutorials
- Awesome Python: [Link] - Curated libraries

Community:
- PyCon talks (YouTube) for staying current with ecosystem trends
- Python Developer Survey (annual) for community tooling insights
- Local Python meetups for networking and knowledge sharing
- Python Discord and Discourse for real-time help and discussion

You might also like