python-dev-practices

majiayu000's avatarfrom majiayu000

Python development best practices for modern Python projects. Activated when working with Python files, pyproject.toml, or discussing Python patterns, testing, linting, type hints.

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 5, 2026

When & Why to Use This Skill

This Claude skill serves as a comprehensive authority on modern Python development, enforcing industry-standard best practices for high-quality software engineering. It prioritizes type safety, minimal dependency overhead, and robust testing methodologies. By integrating modern Python 3.10+ features and advanced tooling like uv and Ruff, it helps developers build maintainable, secure, and performant codebases while ensuring strict adherence to professional coding conventions.

Use Cases

  • Project Architecture & Setup: Establishing modern Python project structures using pyproject.toml and uv for efficient dependency and environment management.
  • Type Safety & Static Analysis: Implementing rigorous type hinting and narrowing (TypeIs, ReadOnly) to eliminate runtime errors and improve code self-documentation.
  • Modernizing Legacy Code: Refactoring older Python scripts to utilize modern features such as structural pattern matching, slots, and frozen dataclasses for better performance.
  • Comprehensive Testing Strategies: Designing multi-layered testing suites that incorporate unit tests, property-based testing, and fuzzing to ensure edge-case robustness.
  • Security & Input Validation: Applying secure coding patterns, including safe path resolution and shell-injection prevention, to protect applications from common vulnerabilities.
namepython-dev-practices
descriptionPython development best practices for modern Python projects. Activated when working with Python files, pyproject.toml, or discussing Python patterns, testing, linting, type hints.

Python development practices

Purpose

Comprehensive guide for Python development covering modern Python practices, type safety, testing strategies, and coding conventions.

When to use

This skill activates when:

  • Creating or modifying Python files
  • Working with pyproject.toml configuration
  • Writing property-based or fuzz tests
  • Handling type hints and type safety
  • Setting up development environment
  • Configuring linting, formatting, or type checking

Core principles

Minimal dependencies philosophy

CRITICAL: Standard library first, dependencies last.

  • ALWAYS prefer standard library solutions
  • Evaluate stdlib before considering third-party code
  • Implementation over dependencies

Type safety requirements

MANDATORY: Comprehensive type hints for ALL code

from typing import Protocol
from typing_extensions import TypeIs, ReadOnly, TypedDict

class Config(TypedDict):
    """Configuration with immutable fields."""
    name: ReadOnly[str]
    options: ReadOnly[list[str]]

def is_valid_config(value: object) -> TypeIs[Config]:
    """Type narrowing with TypeIs."""
    return isinstance(value, dict) and 'name' in value

Modern Python features

Leverage Python 3.10+ capabilities:

# Pattern matching (3.10+)
match argument:
    case {"type": "option", "name": str(name)}:
        return process_option(name)
    case {"type": "value", "data": list(data)}:
        return process_value(data)
    case _:
        raise ValueError(f"Unknown argument: {argument}")

# Dataclasses with slots and frozen
from dataclasses import dataclass

@dataclass(slots=True, frozen=True)
class Result:
    """Immutable result with memory efficiency."""
    success: bool
    data: dict[str, Any]
    errors: list[str]

Import organization

Follow project conventions with isort/Ruff:

# Standard library imports first
import sys
from collections.abc import Sequence
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Protocol

# Third-party (minimal)
from typing_extensions import Doc, ReadOnly, TypeIs

# Local imports
from yourpackage._module import Module
from yourpackage.validation import Validator

Class organization standards

MANDATORY class member ordering:

class Processor:
    # 1. Class State: Constants and class attributes
    DEFAULT_CONFIG = "default"
    RESERVED_NAMES = frozenset(["__init__", "__new__"])

    # 2. Lifecycle: __init__ and __new__
    def __init__(self, config: Config) -> None:
        self._config = config
        self._state = ProcessorState()

    # 3. Magic Methods: __repr__, __str__, __len__
    def __repr__(self) -> str:
        return f"Processor(config={self._config!r})"

    # 4. Public Interface: Properties, then public methods
    @property
    def name(self) -> str:
        return self._config.get("name", self.DEFAULT_CONFIG)

    def process(self, data: Sequence[str]) -> Result:
        """Process data."""
        return self._process_impl(list(data))

    # 5. Internals: Private/protected methods at bottom
    def _process_impl(self, data: list[str]) -> Result:
        pass

Testing strategy

Domain-centric test organization

tests/
├── unit/
│   ├── processing/
│   │   ├── test_data_processing.py
│   │   └── test_transformations.py
│   └── validation/
│       └── test_input_validation.py
├── properties/
│   └── test_invariants.py
└── fuzz/
    └── test_fuzzing.py

Error handling patterns

class AppError(Exception):
    """Base exception for application."""
    pass

class ValidationError(AppError):
    """Raised when validation fails."""

    def __init__(self, message: str, field: str | None = None) -> None:
        super().__init__(message)
        self.field = field

def process_data(data: Sequence[str]) -> Result:
    """Process with clear error messages."""
    if not data:
        raise ValidationError("No data provided")

    try:
        return _process_impl(data)
    except ValueError as e:
        raise ValidationError(f"Invalid data format: {e}") from e

Package management with uv

Essential commands

# CRITICAL: ALWAYS use 'uv run python' for script execution
uv run python scripts/analyze.py
uv run python -m yourpackage

# Install dependencies
uv sync

# Run tools
uv run pytest
uv run ruff check .
uv run basedpyright

Code quality tools

Configuration (pyproject.toml)

[project]
requires-python = ">=3.14"
dependencies = ["typing-extensions>=4.8"]

[tool.basedpyright]
typeCheckingMode = "strict"
pythonVersion = "3.14"

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

[tool.ruff.lint]
select = ["ALL"]
ignore = ["D", "ANN101", "ANN102"]

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--strict-markers --cov=src --cov-report=term-missing"

Security practices

import shlex
from pathlib import Path

def validate_input(user_input: str) -> str:
    """Validate and sanitize user input."""
    # Prevent command injection
    if any(char in user_input for char in [';', '|', '&', '`', '$']):
        raise ValueError("Invalid characters in input")
    return shlex.quote(user_input)

def safe_path_resolution(user_path: str, base: Path) -> Path:
    """Safely resolve paths to prevent traversal."""
    path = (base / user_path).resolve()
    if not path.is_relative_to(base):
        raise ValueError("Path traversal detected")
    return path

Quick reference

Testing checklist

  • Unit tests with >95% coverage
  • Property-based tests for invariants
  • Fuzz tests for robustness
  • Benchmarks for critical paths
  • Type checking passes (basedpyright)
  • Linting passes (ruff)
  • Domain-centric test organization

Remember: Prioritize type safety, comprehensive testing, and standard library usage in all development.