python-best-practices
Skill1 starsChanged 8 months agoApache-2.0View on GitHub
Writes, reviews and scaffolds modern Python 3.14+ code with strict type hints, ruff, uv, src layout and pyproject.toml, async/await with TaskGroup, dataclasses vs Pydantic v2, and pytest conventions. Use when writing or reviewing a .py file, starting a Python project, choosing dataclass or Pydantic, configuring ruff, mypy or pyright, fixing async or blocking-IO bugs, or writing pytest tests.
- Installs packages
19 other projects use a version of this.
Adopted by
Most recently taken up by
- The-AIOS/aiostheir own version, first seen Nov 3, 2026
- medy-gribkov/arcanaword for word, first seen Nov 1, 2026
- jkitchin/knowhowtheir own version, first seen Nov 1, 2026
- OpenxIntelligence/Coding-Agent-Skillstheir own version, first seen Nov 1, 2026
- fullerzz/agent-skillstheir own version, first seen Oct 25, 2026
- I-Onlabs/claude-code-skillstheir own version, first seen Oct 25, 2026
Used with
Projects with it also use react-best-practices, typescript-best-practices and 3 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
OpenAISkillreact-best-practices
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
Also in 3 projects that use this
jaydubya818Skilltypescript-best-practices
Use when TypeScript needs focused type-safety, API, or error-handling guidance.
Also in 3 projects that use this
BlockSkillfrontend-design
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Also in 4 projects that use this
SentrySkillskill-creator
Create new agent skills following the Agent Skills specification. Use when asked to "create a skill", "add a new skill", "write a skill", "make a skill", "build a skill", or scaffold a new skill with SKILL.md. Guides through requirements, writing, registration, and verification.
Also in 4 projects that use this
GoogleSkilltdd
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
Also in 3 projects that use this
Other versions19 projects use a version of this.
Word for word · 1
- medy-gribkov/arcana★ 1100% same
Edited · 0
None found.
Wrote their own version · 18
- The-AIOS/aios★ 105same name
- jefflester/claude-skills-supercharged★ 43same name
- baekenough/oh-my-customcode★ 42same name
- jkitchin/knowhow★ 42same name
- excatt/superclaude-plusplus★ 14same name
- arnabdeypolimi/claude_code_setup★ 4same name
- I-Onlabs/claude-code-skills★ 4same name
- OpenxIntelligence/Coding-Agent-Skills★ 4same name
- Sanskar015/claude-skills-supercharged★ 3same name
- amirrezaalasti/codescribe★ 2same name
8 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository21 other files it gives its agents.
- accessibility-wcagSkill
- api-designSkill
- bugbounty-reportSkill
- ci-cd-pipelinesSkill
- codebase-analysisSkill
- database-designSkill
- design-docSkill
- docker-kubernetesSkill
- git-workflowSkill
- go-devSkill
- i18n-localizationSkill
- llm-integrationSkill
- nextjs-16Skill
- oauth-authSkill
- performance-optimizationSkill
- scraping-automationSkill
- security-reviewSkill
- seo-metaSkill
- tailwind-cssSkill
- testingSkill
- ts-devSkill
The file
We split this skill into the rules it gives an agent
11 rules. 0 are common, 0 are distinctive, and 11 are very specific to this project.
0
Common
Most of the 14 edited versions we read keep these.
0
Distinctive
This author's own choices. Worth a look.
11
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 142
Never use Any unless interfacing with untyped third-party code.
- Very specific: line 144
Use X | None not Optional[X] (3.10+ syntax).
- Very specific: line 145
Use collections.abc types for parameters (Sequence, Mapping, Iterable), concrete types for return values (list, dict).
- Very specific: line 218
Use httpx not requests for async HTTP.
- Very specific: line 219
Never call blocking IO (open(), time.sleep(), requests calls) in async code.
- Very specific: line 220
Use TaskGroup (3.11+) over raw gather for structured concurrency and better error handling.
- Very specific: line 277
Bare except: Never except: or except Exception: without re-raising.
- Very specific: line 278
String formatting with
%or.format(): Use f-strings: f"Hello {name}". - Very specific: line 280
Nested dicts for structured data: Use dataclasses or Pydantic.
- Very specific: line 281
os.pathfor path manipulation: Use pathlib.Path everywhere. - Very specific: line 282
print()for logging: Use logging module or structlog for structured logging.
“Common” is measured: kept by at least 6 in 10 of the 14 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
You are a Python expert specializing in modern Python 3.14+ with strict typing, fast tooling (ruff, uv), and production-grade patterns.
Use this skill when
- Writing or reviewing Python code
- Setting up Python project structure and tooling
- Choosing between dataclasses, Pydantic, attrs
- Building async Python services or CLI tools
- Configuring linting, testing, or packaging
Project Structure (src layout)
myproject/
pyproject.toml
src/
myproject/
__init__.py
main.py
models.py
services/
__init__.py
user.py
tests/
conftest.py
test_models.py
test_services/
test_user.pyThe src/ layout prevents accidental imports of the local package without installing it. Always use it for libraries. Flat layout is acceptable for single-file scripts and small apps only.
pyproject.toml (single source of truth)
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.14"
dependencies = [
"httpx>=0.27",
"pydantic>=2.6",
]
[dependency-groups]
dev = ["ruff", "pytest", "pytest-asyncio", "mypy", "pyright", "pre-commit"]
[project.scripts]
myproject = "myproject.main:cli"
[tool.ruff]
target-version = "py314"
line-length = 100
src = ["src"]
[tool.ruff.lint]
select = [
"E", "F", "W", # pyflakes + pycodestyle
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"B", # flake8-bugbear
"A", # flake8-builtins
"SIM", # flake8-simplify
"RUF", # ruff-specific
"ANN", # flake8-annotations (type hint enforcement)
"PT", # flake8-pytest-style
]
[tool.ruff.lint.isort]
known-first-party = ["myproject"]
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
[tool.mypy]
strict = true
python_version = "3.14"
[tool.pyright]
pythonVersion = "3.14"
typeCheckingMode = "strict"
reportMissingTypeStubs = falseuv Package Manager
# Install uv (replaces pip, pip-tools, virtualenv, pipx)
# Use a package manager or the official installation page:
# https://docs.astral.sh/uv/getting-started/installation/
# macOS: brew install uv
# Windows: winget install astral-sh.uv
# Linux: pipx install uv
# Create project with virtual environment
uv init myproject && cd myproject
uv venv # creates .venv
uv add httpx pydantic # adds to pyproject.toml + installs
uv add --dev ruff pytest # dev dependencies
uv sync # install all deps from lockfile
uv run pytest # run inside venv without activation
uv run ruff check src/ # lint
uv run mypy src/ # type check with mypy
uv run pyright src/ # type check with pyright (faster, VSCode default)Why uv over pip: 10-100x faster, built-in lockfile (uv.lock), replaces 5 tools in one binary, written in Rust.
Type checker comparison:
- mypy: Industry standard, slower, more mature plugins.
- pyright: Faster, VS Code default, better error messages, strict mode catches more edge cases.
Type Hints (strict, everywhere)
from collections.abc import Awaitable, Callable, Mapping, Sequence
# Use builtin generics (3.9+), not typing.List/Dict
def process(items: list[str]) -> dict[str, int]: ...
# Use collections.abc for parameter types (accept more input types)
def find(items: Sequence[str], key: str) -> int | None: ...
# 3.12 type statement for aliases (replaces typing.TypeAlias)
type UserId = int
type Headers = Mapping[str, str]
type Point = tuple[float, float]
type Handler[T] = Callable[[T], Awaitable[None]]
# 3.12 generic syntax with a bound (replaces TypeVar)
def clone[T: Base](obj: T) -> T:
return obj.model_copy()Rules:
- Never use
Anyunless interfacing with untyped third-party code. Even then, cast immediately. - Return types on every function. Parameter types on every parameter.
- Use
X | NonenotOptional[X](3.10+ syntax). - Use
collections.abctypes for parameters (Sequence,Mapping,Iterable), concrete types for return values (list,dict).
Dataclasses vs Pydantic v2
# Dataclass: for internal data containers, no validation needed
from dataclasses import dataclass, field
@dataclass(frozen=True, slots=True)
class Point:
x: float
y: float
label: str = ""
tags: list[str] = field(default_factory=list)
# Pydantic v2: for external data (APIs, config, user input), validates on creation
from pydantic import BaseModel, Field, field_validator
class UserCreate(BaseModel):
model_config = {"strict": True}
name: str = Field(min_length=1, max_length=100)
email: str
age: int = Field(ge=0, le=150)
@field_validator("email")
@classmethod
def validate_email(cls, v: str) -> str:
if "@" not in v:
raise ValueError("invalid email")
return v.lower()Decision rule: Pydantic for boundaries (API input, config files, external data). Dataclasses for everything internal. Never use plain dicts for structured data.
Async/Await Patterns
import asyncio
import httpx
# Concurrent HTTP requests
async def fetch_all(urls: list[str]) -> list[str]:
async with httpx.AsyncClient(timeout=10.0) as client:
tasks = [client.get(url) for url in urls]
responses = await asyncio.gather(*tasks, return_exceptions=True)
results: list[str] = []
for resp in responses:
if isinstance(resp, BaseException):
results.append(f"ERROR: {resp}")
else:
results.append(resp.text)
return results
# Semaphore for rate limiting
async def fetch_limited(urls: list[str], max_concurrent: int = 10) -> list[str]:
sem = asyncio.Semaphore(max_concurrent)
async with httpx.AsyncClient() as client:
async def _get_text(url: str) -> str:
async with sem:
resp = await client.get(url)
return resp.text
return await asyncio.gather(*[_get_text(u) for u in urls])
# Structured concurrency with TaskGroup (3.11+)
async def process_batch(items: list[str]) -> None:
async with asyncio.TaskGroup() as tg:
for item in items:
tg.create_task(process_one(item))
# All tasks complete or all cancelled on first exceptionAsync rules:
- Use
httpxnotrequestsfor async HTTP.aiohttpis also fine. - Never call blocking IO (
open(),time.sleep(),requestscalls) in async code. Useasyncio.to_thread()for unavoidable blocking calls. - Use
TaskGroup(3.11+) over rawgatherfor structured concurrency and better error handling.
Pytest Conventions
# tests/conftest.py: shared fixtures
from collections.abc import AsyncGenerator
import pytest
from myproject.db import Database
@pytest.fixture
async def db() -> AsyncGenerator[Database, None]:
database = Database(":memory:")
await database.connect()
yield database
await database.disconnect()
@pytest.fixture
def sample_user() -> dict[str, str]:
return {"name": "Alice", "email": "alice@example.com"}
# tests/test_user.py
import pytest
from myproject.db import Database
from myproject.models import validate_email
from myproject.services.user import UserError, create_user
async def test_create_user_success(db: Database, sample_user: dict[str, str]) -> None:
user = await create_user(db, **sample_user)
assert user.name == "Alice"
assert user.id is not None
async def test_create_user_duplicate_email(db: Database, sample_user: dict[str, str]) -> None:
await create_user(db, **sample_user)
with pytest.raises(UserError, match="already exists"):
await create_user(db, **sample_user)
@pytest.mark.parametrize("email,valid", [
("user@example.com", True),
("invalid", False),
("", False),
("a@b.co", True),
])
def test_email_validation(email: str, valid: bool) -> None:
if valid:
assert validate_email(email) == email.lower()
else:
with pytest.raises(ValueError):
validate_email(email)Pytest rules: Name files test_*.py. Name functions test_*. Use fixtures, not setUp/tearDown. Use parametrize for data-driven tests. Use conftest.py for shared fixtures (pytest discovers them automatically).
Anti-Patterns to Avoid
- Mutable default arguments:
def f(items=[])shares the list across calls. Usedef f(items: list[str] | None = None)thenitems = items or []. - Bare except: Never
except:orexcept Exception:without re-raising. Catch specific exceptions. - String formatting with
%or.format(): Use f-strings:f"Hello {name}". import *: Never in production code. Pollutes namespace, breaks type checkers.- Nested dicts for structured data: Use dataclasses or Pydantic.
data["user"]["address"]["city"]is untyped and crashes with KeyError. os.pathfor path manipulation: Usepathlib.Patheverywhere.print()for logging: Useloggingmodule orstructlogfor structured logging.- Not using
if __name__ == "__main__":in executable modules. - Global mutable state: Pass dependencies as parameters. Use dependency injection.
- Ignoring ruff/mypy warnings: Fix them. They catch real bugs.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

