The Complete Python Developer Guide
A reference-quality, deep-dive guide for professional Python developers — from core language internals to the modern AI agent stack.
Language Mastery, Best Practices, Design Patterns, Ecosystem & AI/Agentic Tooling
A reference-quality, deep-dive guide for professional Python developers — from core language internals to the modern AI agent stack.
Table of Contents
- Language Fundamentals & Internals
- Modern Python Features (3.10 → 3.13+)
- Typing System Deep Dive
- Best Practices & Code Quality
- Design Patterns in Python
- Concurrency & Parallelism
- Testing Ecosystem
- Packaging, Environments & Tooling
- Web Frameworks & APIs
- Data Engineering & Scientific Stack
- Databases & ORMs
- CLI, Logging, Observability
- DevOps, CI/CD & Deployment
- AI / Agentic Engineering Stack
- Recommended Project Structure
- Curated “Must-Know” Library Cheat Sheet
1. Language Fundamentals & Internals
1.1 The Data Model
Python’s “magic” (dunder) methods define how objects behave with built-in operations. Mastering the data model is what separates idiomatic Python from “Python written like Java/C++.”
class Vector:
__slots__ = ("x", "y") # memory-efficient, disables __dict__
def __init__(self, x: float, y: float):
self.x, self.y = x, y
def __repr__(self) -> str:
return f"Vector({self.x!r}, {self.y!r})"
def __add__(self, other: "Vector") -> "Vector":
return Vector(self.x + other.x, self.y + other.y)
def __eq__(self, other: object) -> bool:
return isinstance(other, Vector) and (self.x, self.y) == (other.x, other.y)
def __hash__(self) -> int:
return hash((self.x, self.y))
def __iter__(self):
yield self.x
yield self.y
Key dunder groups to know:
- Construction/representation:
__init__,__new__,__repr__,__str__,__format__ - Comparison:
__eq__,__lt__,functools.total_ordering - Container protocol:
__len__,__getitem__,__setitem__,__contains__,__iter__ - Callable objects:
__call__ - Context managers:
__enter__,__exit__(and__aenter__/__aexit__for async) - Descriptors:
__get__,__set__,__delete__(power behindproperty, ORMs,functools.cached_property) - Attribute access hooks:
__getattr__,__getattribute__,__setattr__
1.2 Everything Is an Object, Names Are References
Variables are labels bound to objects, not containers. This explains mutable default argument bugs, shallow vs. deep copy semantics (copy.copy vs copy.deepcopy), and why is checks identity while == checks equality.
# Classic gotcha
def append_item(item, bucket=[]): # BAD: mutable default shared across calls
bucket.append(item)
return bucket
def append_item_fixed(item, bucket=None):
bucket = bucket if bucket is not None else []
bucket.append(item)
return bucket
1.3 Iterators, Generators & Coroutines
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# Generator expression — lazy, memory-efficient
squares = (x * x for x in range(1_000_000))
# yield from delegates to a sub-generator
def chain(*iterables):
for it in iterables:
yield from it
Generators underpin asyncio coroutines, itertools pipelines, and memory-safe streaming of large datasets.
1.4 Decorators & Closures
import functools
import time
def retry(times: int = 3, delay: float = 1.0):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
last_exc = None
for attempt in range(times):
try:
return func(*args, **kwargs)
except Exception as exc:
last_exc = exc
time.sleep(delay)
raise last_exc
return wrapper
return decorator
@retry(times=5, delay=0.5)
def flaky_call():
...
Always use functools.wraps to preserve __name__, __doc__, and signature introspection.
1.5 Context Managers
from contextlib import contextmanager
@contextmanager
def timer(label: str):
start = time.perf_counter()
try:
yield
finally:
print(f"{label}: {time.perf_counter() - start:.4f}s")
with timer("db-query"):
run_query()
1.6 Metaclasses & __init_subclass__
Metaclasses control class creation; __init_subclass__ is the lighter-weight modern alternative for plugin/registry patterns:
class PluginBase:
registry: dict[str, type] = {}
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
PluginBase.registry[cls.__name__] = cls
1.7 The GIL & Memory Model
- CPython uses a Global Interpreter Lock — only one thread executes Python bytecode at a time.
- Python 3.13 introduced an experimental free-threaded build (PEP 703, “no-GIL” CPython) — a major shift for true multi-core parallelism with threads.
- CPython uses reference counting + a generational garbage collector for cycle detection (
gcmodule). - Implication: CPU-bound work → multiprocessing or native extensions; I/O-bound work → threading or asyncio.
2. Modern Python Features (3.10 → 3.13+)
| Version | Landmark Features |
|---|---|
| 3.10 | Structural pattern matching (match/case), better error messages, X | Y union syntax |
| 3.11 | Massive interpreter speedups (Faster CPython project), exception groups (except*), Self type, tomllib |
| 3.12 | New type parameter syntax (class Stack[T]), f-string parser overhaul, buffer protocol improvements |
| 3.13 | Free-threaded (no-GIL) experimental build, JIT (experimental), improved REPL, better error tracebacks |
2.1 Structural Pattern Matching
def handle_event(event: dict):
match event:
case {"type": "click", "x": x, "y": y}:
print(f"Click at ({x}, {y})")
case {"type": "key", "key": ("Enter" | "Return")}:
submit_form()
case {"type": str() as t}:
print(f"Unknown event type: {t}")
case _:
raise ValueError("Malformed event")
2.2 New Generic Syntax (3.12+)
class Stack[T]:
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
def first[T](items: list[T]) -> T:
return items[0]
2.3 Exception Groups
try:
async with asyncio.TaskGroup() as tg:
tg.create_task(fetch("a"))
tg.create_task(fetch("b"))
except* ValueError as eg:
for e in eg.exceptions:
log.error(e)
3. Typing System Deep Dive
Type hints are optional but essential in professional codebases — they enable IDE support, static analysis, and self-documenting APIs.
from typing import TypedDict, Protocol, Literal, overload
from collections.abc import Sequence, Callable
class UserDict(TypedDict):
id: int
name: str
role: Literal["admin", "member", "guest"]
class Comparable(Protocol):
def __lt__(self, other) -> bool: ...
def sort_items[T: Comparable](items: Sequence[T]) -> list[T]:
return sorted(items)
@overload
def parse(value: str) -> int: ...
@overload
def parse(value: bytes) -> int: ...
def parse(value):
return int(value)
Static type checkers: mypy (reference implementation), pyright/pylance (fast, used by VS Code), pyre (Meta). Use mypy --strict or pyright --strict in CI for maximum safety.
Runtime validation: Static types are erased at runtime — use Pydantic or typeguard/beartype when you need runtime enforcement (e.g., parsing untrusted input, API boundaries).
4. Best Practices & Code Quality
4.1 Style & Structure
- Follow PEP 8 (style) and PEP 257 (docstrings). Use Google-style or NumPy-style docstrings consistently.
- One tool now covers linting and formatting: Ruff (Rust-based, replaces Flake8 + isort + pyupgrade + and largely Black for formatting).
- Keep functions small and single-purpose; prefer composition over deep inheritance.
- Use
pathlib.Pathinstead of raw string path manipulation. - Prefer f-strings over
%or.format().
4.2 Error Handling
class DomainError(Exception):
"""Base class for all domain-specific errors."""
class InsufficientFundsError(DomainError):
def __init__(self, balance: float, requested: float):
self.balance = balance
self.requested = requested
super().__init__(f"Balance {balance} < requested {requested}")
- Never use bare
except:. Catch specific exceptions. - Use custom exception hierarchies per domain/module.
- Fail fast; validate inputs at boundaries (API layer, CLI layer).
4.3 Configuration Management
- pydantic-settings for typed, validated env-based config.
- python-dotenv for
.envloading in dev.
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
debug: bool = False
model_config = {"env_file": ".env"}
4.4 Logging (never print in production code)
import logging
logger = logging.getLogger(__name__)
logger.info("Processing order %s", order_id)
Use structured logging (structlog) for JSON logs in production, correlation IDs, and log aggregation compatibility.
4.5 Security Practices
- Never hardcode secrets — use env vars / secret managers (AWS Secrets Manager, Vault, Doppler).
- Use
banditfor static security scanning. - Pin dependencies with lockfiles; scan with
pip-audit/safety. - Validate all external input (Pydantic models at every trust boundary).
4.6 Documentation
mkdocs+mkdocs-materialorSphinxfor docs sites.- Docstrings + type hints = auto-generated API references.
- Maintain a
CHANGELOG.md(Keep a Changelog format) and semantic versioning.
5. Design Patterns in Python
Python’s dynamic nature makes many classic GoF patterns simpler or unnecessary — but the ideas remain valuable.
5.1 Creational
- Factory Function — plain functions/callables instead of Factory classes.
- Builder — fluent chained methods, or simply keyword-argument-rich dataclasses.
- Singleton — module-level instance (modules are singletons naturally), or
functools.lru_cache(maxsize=None)on a constructor function.
@functools.lru_cache(maxsize=None)
def get_settings() -> Settings:
return Settings()
5.2 Structural
- Adapter — wrap an incompatible interface.
- Decorator (structural, not
@decoratorsyntax) — wrap objects to add behavior. - Facade — a simplified API in front of a complex subsystem (common in SDK wrapper design).
5.3 Behavioral
- Strategy — pass functions as first-class objects instead of Strategy classes.
def process(data: list[int], strategy: Callable[[list[int]], int]) -> int:
return strategy(data)
process(data, strategy=sum)
process(data, strategy=max)
- Observer — event systems,
blinkerlibrary, or simple pub/sub with callback lists. - Command — encapsulate a request as an object (used heavily in task queues / undo systems).
- State Machine —
transitionsorpython-statemachinelibraries for explicit FSMs.
5.4 Dependency Injection
Python rarely needs a DI framework thanks to duck typing, but for larger apps:
- FastAPI’s
Depends()system. dependency-injectorlibrary for explicit containers in non-web apps.
5.5 Repository & Unit of Work (DDD-adjacent)
Common in service-layer architectures to decouple business logic from persistence (SQLAlchemy session scope as Unit of Work).
6. Concurrency & Parallelism
| Model | Use Case | Tooling |
|---|---|---|
| Threading | I/O-bound, blocking libraries | threading, concurrent.futures.ThreadPoolExecutor |
| Asyncio | I/O-bound, high concurrency (network, DB) | asyncio, httpx, aiohttp, asyncpg |
| Multiprocessing | CPU-bound | multiprocessing, concurrent.futures.ProcessPoolExecutor, joblib |
| Distributed | Cross-machine parallelism | Celery, Dask, Ray |
import asyncio
async def fetch_all(urls: list[str]):
async with httpx.AsyncClient() as client:
tasks = [client.get(url) for url in urls]
return await asyncio.gather(*tasks)
# Structured concurrency (3.11+)
async def main():
async with asyncio.TaskGroup() as tg:
tg.create_task(fetch_all(urls_a))
tg.create_task(fetch_all(urls_b))
- Ray is increasingly the go-to for distributed compute in ML/AI pipelines (also underlies many agent-serving frameworks).
- Dask mirrors pandas/numpy APIs for out-of-core / distributed dataframes.
7. Testing Ecosystem
- pytest — the de facto standard; fixtures, parametrization, plugins.
- pytest-asyncio — testing async code.
- pytest-cov — coverage integration.
- hypothesis — property-based testing (generates edge cases automatically).
- tox / nox — test across multiple Python versions/environments.
- factory_boy / faker — test data generation.
- responses / respx — mocking HTTP calls.
- testcontainers-python — spin up real Docker dependencies (Postgres, Redis) for integration tests.
import pytest
@pytest.fixture
def client():
return TestClient(app)
@pytest.mark.parametrize("value,expected", [(1, 2), (2, 4), (3, 6)])
def test_double(value, expected):
assert double(value) == expected
@pytest.mark.asyncio
async def test_fetch():
result = await fetch_data()
assert result is not None
8. Packaging, Environments & Tooling
8.1 Modern Toolchain (2025-2026 consensus)
- uv (Astral) — the new standard: blazing-fast package installer, resolver, and project manager (replaces pip, pip-tools, virtualenv, and largely Poetry for many teams).
- Ruff (Astral) — linter + formatter, replacing Flake8/isort/Black in most new projects.
- Poetry — still widely used for dependency + packaging management with
pyproject.toml. - pyenv — manage multiple Python interpreter versions.
- pipx — install/run CLI tools in isolated environments.
# uv workflow
uv init my-project
uv add fastapi httpx
uv run pytest
uv lock
8.2 pyproject.toml (PEP 621) is the single source of truth
[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["fastapi>=0.115", "pydantic>=2.0"]
[tool.ruff]
line-length = 100
[tool.mypy]
strict = true
8.3 Pre-commit Hooks
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
hooks:
- id: ruff
- id: ruff-format
9. Web Frameworks & APIs
| Framework | Best For |
|---|---|
| FastAPI | Modern async APIs, auto OpenAPI docs, Pydantic-native — default choice for new services (and the backbone of most AI-serving APIs) |
| Django | Full-stack batteries-included apps, admin panel, ORM, auth |
| Django REST Framework | REST APIs on top of Django |
| Flask | Lightweight, micro-services, simple apps |
| Litestar | Performance-focused FastAPI alternative with strong DI |
| Starlette | ASGI toolkit underlying FastAPI |
from fastapi import FastAPI, Depends
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.post("/items")
async def create_item(item: Item):
return {"id": 1, **item.model_dump()}
Serving: Uvicorn (ASGI server), Gunicorn (with Uvicorn workers) for production.
10. Data Engineering & Scientific Stack
- NumPy — foundational n-dimensional array computing.
- pandas — tabular data manipulation (industry default).
- Polars — Rust-based, multi-threaded DataFrame library; dramatically faster than pandas for large data, increasingly the modern default.
- PyArrow — columnar in-memory format, interop layer for pandas/Polars/Spark.
- DuckDB — embedded analytical SQL engine, excellent for local analytics on Parquet/CSV.
- Matplotlib / Seaborn / Plotly — visualization.
- scikit-learn — classical ML.
- PyTorch — deep learning (dominant framework for research and increasingly production).
- JAX — high-performance numerical computing + autodiff, popular in research.
import polars as pl
df = pl.read_parquet("events.parquet")
result = (
df.filter(pl.col("status") == "active")
.group_by("country")
.agg(pl.col("revenue").sum())
)
11. Databases & ORMs
- SQLAlchemy 2.0 — the standard ORM/Core toolkit, fully async-capable with
asyncpg/aiomysql. - SQLModel — SQLAlchemy + Pydantic combined, from the FastAPI author.
- Alembic — schema migrations for SQLAlchemy.
- Django ORM — tightly coupled to Django, very productive for CRUD-heavy apps.
- Tortoise ORM — async-first, Django-ORM-like API.
- asyncpg / psycopg3 — PostgreSQL drivers.
- Redis-py — caching, pub/sub, queues.
- MongoDB (PyMongo / Motor) — document store, async via Motor.
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase
class Base(DeclarativeBase): pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
email: Mapped[str]
12. CLI, Logging, Observability
- Typer — modern CLI framework built on type hints (from the FastAPI author).
- Click — mature, composable CLI framework (underlies Typer).
- Rich — beautiful terminal output, tables, progress bars, tracebacks.
- structlog — structured logging.
- OpenTelemetry — distributed tracing/metrics standard, framework-agnostic.
- Sentry — error tracking/monitoring.
- Prometheus client — metrics exposition for scraping.
import typer
from rich import print
app = typer.Typer()
@app.command()
def greet(name: str, loud: bool = False):
msg = f"Hello, {name}!"
print(msg.upper() if loud else msg)
if __name__ == "__main__":
app()
13. DevOps, CI/CD & Deployment
- Docker — containerization; use multi-stage builds +
uv/pip --no-cache-dirfor slim images. - GitHub Actions / GitLab CI — standard CI/CD.
- Kubernetes — orchestration for larger deployments.
- Terraform — infra-as-code (often paired with Python via
pulumifor Python-native IaC). - Pulumi — infra-as-code written in actual Python.
- Makefile or just (command runner) for standardized dev commands.
FROM python:3.13-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
FROM python:3.13-slim
COPY --from=builder /app /app
CMD ["uv", "run", "uvicorn", "main:app", "--host", "0.0.0.0"]
14. AI / Agentic Engineering Stack
This section covers the libraries and patterns essential for building LLM-powered applications and autonomous agents in 2025-2026.
14.1 Core LLM SDKs
anthropic— official Claude SDK (Messages API, tool use/function calling, streaming, batch API, prompt caching).openai— official OpenAI SDK (Chat Completions/Responses API, function calling, Assistants/Realtime API).litellm— unified interface across 100+ LLM providers with a single OpenAI-compatible API — extremely popular for provider-agnostic apps.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=[{
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {
"type": "object",
"properties": {"location": {"type": "string"}},
"required": ["location"],
},
}],
messages=[{"role": "user", "content": "What's the weather in Istanbul?"}],
)
14.2 Structured Output & Validation
- Pydantic v2 — the backbone of nearly every agent framework; defines tool schemas, validates LLM output, powers FastAPI request/response models.
instructor— patches LLM clients to return validated Pydantic objects directly from completions (huge for reliable structured extraction).outlines— constrained/guided generation (grammars, regex, JSON schema enforcement) at the token level for open-weight models.
import instructor
from pydantic import BaseModel
class Person(BaseModel):
name: str
age: int
client = instructor.from_anthropic(anthropic.Anthropic())
person = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
response_model=Person,
messages=[{"role": "user", "content": "Extract: John is 30 years old"}],
)
14.3 Agent Orchestration Frameworks
| Framework | Philosophy |
|---|---|
| LangGraph | Graph-based, low-level, explicit state machines for agents — the current favorite for production-grade, controllable agent workflows; built by the LangChain team |
| LangChain | Broad ecosystem of chains, retrievers, memory, integrations — good for rapid prototyping, RAG pipelines |
| CrewAI | Role-based multi-agent orchestration (agents as “crew members” with roles/goals/tasks) |
| AutoGen (AG2) / Microsoft Agent Framework | Conversation-driven multi-agent systems, strong in research/enterprise settings |
| LlamaIndex | Data framework specialized in RAG — indexing, retrieval, query engines over documents |
| Semantic Kernel | Microsoft’s SDK, plugin/skill-based orchestration, strong .NET/Python parity |
| OpenAI Agents SDK | Lightweight official agent/handoff/guardrail primitives from OpenAI |
| Pydantic AI | Type-safe, Pydantic-native agent framework — minimal, testable, dependency-injection style |
| smolagents (Hugging Face) | Minimalist, code-writing agents (agents that write & execute Python to act) |
# LangGraph-style explicit agent state machine (conceptual)
from langgraph.graph import StateGraph, END
class AgentState(TypedDict):
messages: list
next_step: str
graph = StateGraph(AgentState)
graph.add_node("plan", plan_node)
graph.add_node("act", act_node)
graph.add_node("reflect", reflect_node)
graph.add_conditional_edges("reflect", should_continue, {"continue": "plan", "done": END})
graph.set_entry_point("plan")
app = graph.compile()
14.4 The Model Context Protocol (MCP)
MCP (introduced by Anthropic, now widely adopted across the industry) is an open standard for connecting LLM applications to external tools, data sources, and services — think “USB-C for AI applications.” Key building blocks:
mcpPython SDK — build MCP servers/clients.- Servers expose tools, resources, and prompts over a standard JSON-RPC-based transport (stdio, HTTP/SSE).
- Rapidly becoming the standard way agent frameworks (Claude, LangGraph, CrewAI, custom agents) discover and call external tools, replacing bespoke tool-calling glue code.
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather-server")
@mcp.tool()
def get_forecast(city: str) -> str:
"""Get weather forecast for a city."""
return fetch_weather(city)
if __name__ == "__main__":
mcp.run()
14.5 Vector Databases & Retrieval (RAG)
- Chroma — simple, embedded, popular for local/dev RAG.
- Qdrant — high-performance, Rust-based, strong filtering support.
- Weaviate — hybrid search (vector + keyword), schema-based.
- Pinecone — fully managed, serverless vector DB.
- pgvector — vector search as a Postgres extension (great when you already run Postgres).
- FAISS (Meta) — in-process similarity search library, foundational/low-level.
import chromadb
client = chromadb.PersistentClient(path="./db")
collection = client.get_or_create_collection("docs")
collection.add(documents=[...], ids=[...], embeddings=[...])
results = collection.query(query_texts=["What is RAG?"], n_results=5)
14.6 Embeddings & Reranking
sentence-transformers— open-source embedding/reranking models.- OpenAI / Voyage AI / Cohere embedding APIs — hosted, high-quality embeddings.
- Cohere Rerank / cross-encoder rerankers — improve retrieval precision post-vector-search.
14.7 Observability & Evaluation for LLM Apps
- LangSmith — tracing, evaluation, dataset management (LangChain ecosystem).
- Langfuse — open-source LLM observability, tracing, prompt management, evals.
- Helicone — proxy-based LLM logging/observability/cost tracking.
- Ragas — RAG-specific evaluation metrics (faithfulness, context precision/recall).
- promptfoo — prompt testing/regression framework, CI-friendly.
- DeepEval — pytest-style unit testing framework for LLM outputs.
from ragas import evaluate
from ragas.metrics import faithfulness, context_precision
results = evaluate(dataset, metrics=[faithfulness, context_precision])
14.8 Prompt Engineering & Templates
- Jinja2 — templating engine widely used for dynamic prompt construction.
anthropic/openaiprompt caching — reduce cost/latency for repeated large system prompts/context.- Version prompts like code: store in files/DB, review via PRs, evaluate with promptfoo/Langfuse before deploying.
14.9 Local & Open-Weight Model Serving
- Ollama — simplest way to run open-weight models locally.
- vLLM — high-throughput inference server (PagedAttention), the production standard for self-hosted LLM serving.
- Hugging Face
transformers/accelerate— model loading, fine-tuning, inference. - LoRA / PEFT /
peftlibrary — efficient fine-tuning of large models. - llama.cpp / GGUF — CPU-friendly quantized model inference.
14.10 Multi-Agent Communication & Guardrails
- Guardrails AI — validation/guardrail framework for LLM inputs/outputs (PII detection, toxicity, schema enforcement).
- NeMo Guardrails (NVIDIA) — programmable rails for conversational safety/topic control.
- A2A (Agent2Agent) protocol — emerging standard (Google-led) for agent-to-agent interoperability, complementing MCP’s tool-access focus.
14.11 A Minimal but Realistic Agentic Stack (2026)
LLM: Anthropic Claude / OpenAI GPT (via `anthropic`/`openai`/`litellm`)
Orchestration: LangGraph or Pydantic AI
Tools: MCP servers (custom + community)
Structured I/O: Pydantic v2 + `instructor`
Retrieval: Qdrant/pgvector + sentence-transformers + Cohere Rerank
Observability: Langfuse
Evaluation: Ragas + promptfoo (CI gate)
Serving: FastAPI + Uvicorn, Docker, behind an API gateway
15. Recommended Project Structure
my-project/
├── pyproject.toml
├── uv.lock
├── README.md
├── .pre-commit-config.yaml
├── .github/workflows/ci.yml
├── src/
│ └── my_project/
│ ├── __init__.py
│ ├── api/ # FastAPI routers
│ ├── core/ # config, logging, security
│ ├── domain/ # business models, exceptions
│ ├── services/ # business logic
│ ├── repositories/ # data access
│ ├── agents/ # agent graphs, tools, prompts
│ └── schemas/ # Pydantic models
└── tests/
├── unit/
├── integration/
└── conftest.py
16. Curated “Must-Know” Library Cheat Sheet
| Category | Libraries |
|---|---|
| Package/env management | uv, poetry, pyenv, pipx |
| Lint/format/type-check | ruff, mypy, pyright |
| Testing | pytest, hypothesis, tox, nox, testcontainers |
| Web frameworks | fastapi, django, flask, litestar |
| Data validation | pydantic |
| Data/Scientific | numpy, pandas, polars, pyarrow, duckdb |
| ML/DL | scikit-learn, pytorch, jax, transformers |
| DB/ORM | sqlalchemy, sqlmodel, alembic, asyncpg |
| Async HTTP | httpx, aiohttp |
| CLI | typer, click, rich |
| Logging/Observability | structlog, opentelemetry, sentry-sdk |
| AI/Agentic — LLM SDKs | anthropic, openai, litellm |
| AI/Agentic — orchestration | langgraph, langchain, crewai, autogen, pydantic-ai, llama-index |
| AI/Agentic — structured output | instructor, outlines |
| AI/Agentic — tools/protocol | mcp |
| AI/Agentic — vector DB | chromadb, qdrant-client, weaviate-client, pinecone |
| AI/Agentic — evaluation | ragas, deepeval, promptfoo |
| AI/Agentic — observability | langfuse, langsmith |
| AI/Agentic — serving | vllm, ollama, llama-cpp-python |
Final Notes
- Prioritize readability and explicitness over cleverness — “Simple is better than complex” (The Zen of Python).
- Keep your toolchain lean:
uv+ruff+pytest+mypy/pyrightcovers 90% of professional needs. - In the agentic space specifically, favor explicit, inspectable state machines (LangGraph, Pydantic AI) over “magic” autonomous loops for anything production-critical — controllability and observability matter more than raw autonomy.