Skip to content
Back to skills

Python Best Practices

ASecurity

Use when reading or writing Python files (.py, pyproject.toml, requirements.txt).

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 16, 2026
ai-agentspythonrustgobashtestingapi

Works with

  • api

Security analysis

A100/100

Scanned October 16, 2026

npx -y skills add alleneubank/agent-profile --skill python-best-practices --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Python Best Practices?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Python Best Practices
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/alleneubank-python-best-practices/badge)](https://www.skillsdirectory.com/skills/alleneubank-python-best-practices)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: python-best-practices
description: Use when reading or writing Python files (.py, pyproject.toml, requirements.txt).
---

# Python Best Practices

Follows the type, error, and assertion law in `code-law`. This skill covers language-specific idioms only.

## Make Illegal States Unrepresentable

Use Python's type system to prevent invalid states at type-check time.

**Frozen dataclasses for immutable domain models:**
```python
from dataclasses import dataclass
from datetime import datetime

@dataclass(frozen=True)
class User:
    id: str
    email: str
    name: str
    created_at: datetime

# Frozen dataclasses are immutable — no accidental mutation
```

**Discriminated unions with Literal:**
```python
from dataclasses import dataclass
from typing import Literal

@dataclass
class Success:
    status: Literal["success"] = "success"
    data: str

@dataclass
class Failure:
    status: Literal["error"] = "error"
    error: Exception

RequestState = Success | Failure

def handle_state(state: RequestState) -> None:
    match state:
        case Success(data=data):
            render(data)
        case Failure(error=err):
            show_error(err)
```

**NewType for domain primitives:**
```python
from typing import NewType

UserId = NewType("UserId", str)
OrderId = NewType("OrderId", str)

def get_user(user_id: UserId) -> User:
    # Type checker prevents passing OrderId here
    ...
```

**Protocol for structural typing:**
```python
from typing import Protocol

class Readable(Protocol):
    def read(self, n: int = -1) -> bytes: ...

def process_input(source: Readable) -> bytes:
    # Accepts any object with a read() method — no inheritance required
    return source.read()
```

**Restrict who can do it** — Python cannot hide a call, so keep an effect that needs a scope (a lock, a transaction) inside that scope: a context manager or a method of the object that owns the state, not a free function callers must remember to guard. Correct types are the proof where the type checker can see them.

## Python-Specific Error Handling

Chain exceptions with `from err` to preserve the original traceback:
```python
try:
    data = json.loads(raw)
except json.JSONDecodeError as err:
    raise ValueError(f"invalid JSON payload: {err}") from err
```

## Structured Logging

Use a module-level logger with `%s` formatting (deferred string interpolation):
```python
import logging

logger = logging.getLogger("myapp.widgets")

def create_widget(name: str) -> Widget:
    logger.debug("creating widget: %s", name)
    widget = Widget(name=name)
    logger.debug("created widget id=%s", widget.id)
    return widget
```

## Test Doubles

`assert_has_calls` and `mock_calls` on a `MagicMock` standing in for your own collaborator grade the order of the calls, not the result — the change-detector shape in `testing-best-practices`. Prefer a small class satisfying the `Protocol` and assert its return value; `autospec=True` binds the signature, not the behavior. Reach for `assert_called_once_with` only where firing exactly once *is* the contract.

## Optional: ty

For fast type checking, consider [ty](https://docs.astral.sh/ty/) from Astral (creators of ruff and uv). Written in Rust, significantly faster than mypy or pyright.

```bash
uvx ty check          # run directly, no install needed
uvx ty check src/     # check specific path
```

```toml
# pyproject.toml
[tool.ty]
python-version = "3.12"
```

When to choose:
- `ty` — fastest, good for CI and large codebases (early stage, rapidly evolving)
- `pyright` — most complete type inference, VS Code integration
- `mypy` — mature, extensive plugin ecosystem

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.