Was macht Python-Programmierung — Allgemeiner Ansatz?
Dies ist die zentrale Python-Referenz. Sie enthält die verbindlichen Standardeinstellungen und die „Functional-Lite“-Philosophie, die für den gesamten Python-Code in diesem Projekt gilt. Lies dies zuerst; folge für tiefergehende Anleitungen den verlinkten Bereichs-Skills.
Kern-Stack
| Bereich | Auswahl |
|---|---|
| Paketmanager & Aufgabenausführung | uv |
| Paketmanifest | nur pyproject.toml |
| Linter / Formatierer | ruff |
| Typprüfer | ty |
| Datenverarbeitungsbibliothek | polars (nicht pandas) |
| Backend-Framework | FastAPI |
| Datenbank | PostgreSQL |
| ORM | SQLAlchemy (async) |
| Migrationen | Alembic |
| Laufzeitmodell | asyncio — immer async |
| Programmierstil | Functional-Lite |
Paketverwaltung — Immer uv
Verwende niemals direkt pip, pip-tools, poetry oder pipenv.
Alle Installationen, Ausführungen und Skripte verwenden uv und seine nativen Befehle.
# Abhängigkeiten installieren
uv sync
# Eine Abhängigkeit hinzufügen
uv add <package>
# Eine Entwicklungsabhängigkeit hinzufügen
uv add --dev <package>
# Ein Skript oder Modul ausführen
uv run python script.py
uv run alembic upgrade head
uv run pytest
# Abhängigkeiten aktualisieren
uv lock --upgrade
Pinne alle Produktionsabhängigkeiten mit == für reproduzierbare Builds.
Verwende requirements.txt, requirements-dev.txt oder ein requirements-Verzeichnis nicht für die Abhängigkeitsverwaltung. Sämtliche Paketmetadaten und Abhängigkeitskonfigurationen gehören in pyproject.toml.
Verwende uv für jeden Vorgang, der Pakete, Werkzeuge oder Builds betrifft. Führe in diesem Projekt niemals pip, pip install, python -m pip, poetry oder pipenv direkt aus.
Siehe den Skill upgrade-dependencies für den vollständigen Upgrade-Workflow:
.github/skills/upgrade-dependencies/SKILL.md
Bibliotheksspezifische Anleitungen findest du unter .github/skills/python-library-creation/SKILL.md.
Linting und Formatierung — Astral-Stack Pflicht
Der Astral-Stack ist für Python-Projekte in diesem Repository verpflichtend. ruff ist der kanonische Linter und Formatierer.
- Füge
ruffals Entwicklungsabhängigkeit hinzu:uv add --dev ruff - Verwende
uv run ruff format, um Code zu formatieren. - Verwende
uv run ruff check --fix, um Linting auszuführen und Probleme automatisch zu beheben, wo möglich. - Dokumentiere diese Befehle in deinen Projektskripten oder der README.
ruff ist die einzige Quelle der Wahrheit für Formatierung und Stilkonsistenz in Code, Tests und Konfiguration.
Typprüfung — ty bevorzugt
Typannotationen sind erforderlich. ty ist der bevorzugte Typprüfer für dieses Repository.
- Füge
tyals Entwicklungsabhängigkeit hinzu:uv add --dev ty - Führe Typprüfungen mit
uv run ty checkdurch - Verwende
uv run --with ty ty check, um die Toolchain zu validieren, wenn du Verhaltensweisen vergleichen möchtest.
Das Repository kann weiterhin mit anderen Prüfern wie mypy oder pyrefly experimentieren, aber ty ist der bevorzugte primäre Prüfer und sollte in CI durchgesetzt werden.
Datenverarbeitung — Polars vs DuckDB
Dieses Repository bevorzugt polars für die prozessinterne Datenverarbeitung und DuckDB für SQL-first Analytics und das Abfragen großer Dateien.
-
Verwende Polars, wenn der Agent als Speedster agiert:
- Rust-basiert, Multithread-DataFrame-Verarbeitung auf einem einzigen Rechner.
- Am besten geeignet für komplexe Pipeline-Verkettungen, Feature Engineering, Joins, Fensterfunktionen und programmatische Transformationen.
- Priorisiert Durchsatz und Rechengeschwindigkeit mit strengerer Schema- und Typsicherheit.
- Ausgezeichnet für Modellvorverarbeitung und Integration mit Python-ML-Tools.
-
Verwende DuckDB, wenn der Agent als Bibliothekar agiert:
- In-Prozess-SQL-Datenbank, optimiert für analytische OLAP-Abfragen.
- SQL-first-Ansatz ist zuverlässiger, um natürliche Sprache in Code zu übersetzen.
- Besser für speicherbegrenzte Workloads: DuckDB erzwingt strenge Speicherlimits und kann sehr große Datensätze sicher abfragen.
- Ideal für Zero-ETL direktes Cloud-Abfragen von entfernten Dateien in S3 oder Google Cloud per URL.
Entscheidungsheuristik
Wenn die Aufgabe ist:
- Erkunden neuer Dateien oder Cloud-Speicher → DuckDB
- Am besten geeignet für direktes Datei-Scanning und SQL-Erkundung.
- Filtern oder Sortieren massiver Datensätze → Polars
- Dominieren oft bei roher Filter- und Ladegeschwindigkeit auf einzelnen Knoten.
- Zusammenarbeit oder Übergabe → DuckDB
- SQL ist für Menschen und Agenten einfacher zu warten und zu debuggen.
- Modellvorverarbeitung → Polars
- Bessere Integration mit Python-ML-Tools und schemasicheren Pipelines.
Backend — FastAPI
FastAPI ist das einzige unterstützte Backend-Framework. Wichtige Konventionen:
- Verwende immer
async deffür Route-Handler und Abhängigkeiten. - Verwende Pydantic v2 Modelle für alle Anfrage-/Antwortstrukturen.
- Deklariere Abhängigkeiten mit
Depends()— greife niemals auf globalen Zustand innerhalb von Handlern zu. - Gib typisierte Antwortmodelle zurück; gib niemals rohe Dictionaries von Route-Handlern zurück.
- Router leben in ihren eigenen Modulen;
main.pymountet nur Router und konfiguriert Middleware.
# ✅ Korrektes Muster
@router.get("/items/{item_id}", response_model=ItemResponse)
async def get_item(item_id: int, db: AsyncSession = Depends(get_db)) -> ItemResponse:
return await item_service.get(db, item_id)
Für Strukturierung, Tests, Sicherheit und OpenAPI-Dokumentation siehe die FastAPI-Bereichs-Skills:
.github/skills/python-fastapi-project-structuring/SKILL.md.github/skills/python-fastapi-routing-validation/SKILL.md.github/skills/python-fastapi-dependency-injection/SKILL.md.github/skills/python-fastapi-response-error-handling/SKILL.md.github/skills/python-fastapi-security-authentication/SKILL.md.github/skills/python-fastapi-security-attack-resistance/SKILL.md.github/skills/python-fastapi-api-testing/SKILL.md.github/skills/python-fastapi-openapi-documentation/SKILL.md
Datenbank — PostgreSQL + SQLAlchemy (async)
PostgreSQL ist die einzige unterstützte Datenbank. SQLAlchemy ist das ORM.
- Verwende immer die asynchrone Engine und Session (
AsyncEngine,AsyncSession). - Rufe niemals synchrone SQLAlchemy-APIs aus asynchronem Code auf.
- Verwende
select(),insert(),update(),delete()aussqlalchemy— keine rohen SQL-Strings. - Verwalte den Session-Lebenszyklus mit
async with AsyncSession(engine) as session. - Definiere Modelle mit
DeclarativeBase; verwende typisierteMapped[T]Spaltenannotationen (SQLAlchemy 2.x Stil).
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
engine = create_async_engine("postgresql+asyncpg://...", echo=False)
class Base(DeclarativeBase):
pass
class Item(Base):
__tablename__ = "items"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
Datenbank-Migrationen — Alembic
Alembic verwaltet alle Schemaänderungen. Ändere das Datenbankschema niemals manuell.
Wichtige Regeln:
- Migrationen sind unveränderlich, sobald sie auf eine nicht-lokale Umgebung angewendet wurden.
- Jede Migration sollte wo möglich idempotent sein.
- Verwende
uv run alembicfür alle Alembic-Befehle.
uv run alembic revision --autogenerate -m "add_items_table"
uv run alembic upgrade head
uv run alembic history
uv run alembic current
Vollständige Regeln für das Erstellen von Migrationen und RLS-Durchsetzung findest du unter:
.github/skills/python-alembic-migrations/SKILL.md
Für das Rebasing von nur-lokalen Migrationszweigen siehe:
.github/skills/python-alembic-migration-rebase/SKILL.md
Async — Immer
Jeder I/O-Vorgang muss async sein. Es gibt keinen Platz für blockierende Aufrufe im Anfragepfad.
- Verwende
asyncio.gather()für gleichzeitige unabhängige Coroutinen. - Verwende
asyncio.TaskGroup(Python 3.11+), wenn strukturierte Nebenläufigkeit und Fehler- propagation wichtig sind. - Verwende
asyncio.Queueoderasyncio.Semaphorefür Backpressure und Ratenbegrenzung. - Rufe niemals
time.sleep()auf — verwendeawait asyncio.sleep(). - Verwende niemals
requests— verwendehttpx.AsyncClientoderaiohttp.
Tiefergehende Anleitungen:
.github/skills/python-asyncio/asyncio-concurrent-web-requests/SKILL.md.github/skills/python-concurrent-processing/SKILL.md(CPU-intensive Arbeit →ProcessPoolExecutor+ asyncio-Integration).github/skills/python-asyncio/asyncio-synchronization/SKILL.md
Functional-Lite-Stil
Die Codebasis verwendet einen „Functional-Lite“-Ansatz: Wende funktionale Techniken dort an, wo sie die Komplexität reduzieren und die Klarheit verbessern, aber erzwinge keine theoretische Reinheit um ihrer selbst willen.
Was wir TUN
| Technik | Verwendung |
|---|---|
| Reine Funktionen | Standard für Geschäftslogik. Keine Seiteneffekte, wenn nicht nötig. |
| Unveränderliche Daten | Verwende Frozen Dataclasses / Pydantic-Modelle für Wertobjekte. |
| Funktionen höherer Ordnung | Bevorzuge map, filter, functools.reduce gegenüber imperativen Schleifen für Datenpipelines. |
| Generatoren / faule Sequenzen | Große oder Streaming-Datensätze — vermeide das Erstellen vollständiger Listen im Speicher. |
functools-Dienstprogramme | lru_cache, cache, partial, wraps — frei verwenden. |
| Funktionskomposition | Verkette kleine, fokussierte Funktionen in Datenstransformationspipelines. |
| Beschreibende Dekorateure | Drücke querschnittliche Belange (Auth, Caching, Wiederholungen) als Dekorateure aus. |
Was wir NICHT erzwingen
| Technik | Grund, sie zu vermeiden, es sei denn, sie ist klar vorteilhaft |
|---|---|
Monaden (Maybe, Either, Result) | Erhöht kognitive Belastung; verwende stattdessen Ausnahmen + typisierte Rückgaben. |
| Point-free-Stil | Schadet der Lesbarkeit für die meisten Teammitglieder. |
| Strikte Unveränderlichkeit überall | SQLAlchemy-Modelle und asynchroner Zustand sind von Natur aus veränderlich — bekämpfe das nur dort, wo es wichtig ist. |
pymonad / returns-Bibliothek | Nur Opt-in; erzwinge dies nicht in gemeinsam genutztem Code ohne Teamzustimmung. |
# ✅ Functional-Lite: Pipeline aus fokussierten, reinen Funktionen
from functools import reduce
def parse_items(raw: list[dict]) -> list[Item]:
return [Item(**r) for r in raw if r.get("active")]
def enrich(item: Item, overrides: dict) -> Item:
return item.model_copy(update=overrides.get(item.id, {}))
def process(raw: list[dict], overrides: dict) -> list[Item]:
return [enrich(item, overrides) for item in parse_items(raw)]
Tiefergehende Anleitungen — konsolidierte und spezialisierte funktionale Skills:
.github/skills/python-higher-order-functools/SKILL.md(map, filter, max/min, @cache, partial, reduce, @singledispatch).github/skills/python-lazy-evaluation-pipelines/SKILL.md(yield, yield from, Generator-Pipelines, map/filter/reduce).github/skills/python-immutable-data-design/SKILL.md(NamedTuple, Frozen Dataclass, pyrsistent, Kontextmanager).github/skills/python-functional-programming/python-decorator-design/SKILL.md.github/skills/python-functional-programming/python-functional-web-services/SKILL.md(Funktionale FastAPI-Handler).github/skills/python-functional-programming/python-toolz-composition/SKILL.md.github/skills/python-functional-programming/python-itertools-combinatorics/SKILL.md.github/skills/python-functional-programming/python-recursion-tco/SKILL.md.github/skills/python-functional-programming/python-pymonad-strict-evaluation/SKILL.md← nur Opt-in
Allgemeine Code-Konventionen
- Python 3.11+ Minimum. Verwende moderne Syntax:
match,TypeAlias,Selfusw. - Typ-Annotiere alles — Funktionssignaturen, Variablen, Rückgabetypen.
- Kein
Any, außer bei der Integration mit einer untypisierten Drittanbieter-Grenze. - Bevorzuge
dataclass(frozen=True)oder PydanticBaseModelfür Wertobjekte. - Halte Funktionen klein und für einen einzigen Zweck. Wenn eine Funktion einen Kommentar benötigt, um zu erklären, was sie tut (nicht warum), teile sie auf.
- Vermeide globalen veränderlichen Zustand. Übergebe Abhängigkeiten explizit (Konstruktor oder
Depends()). - Verwende
logging— nichtprint. Konfiguriere beim Anwendungsstart; rufe niemalsbasicConfig()innerhalb von Bibliothekscode auf. Siehe.github/skills/python-configuration-observability/SKILL.mdfür vollständige Anleitungen zu Logging, Tracing und Konfiguration.
Skill-Karte
python/SKILL.md ← du bist hier (zentrale Referenz)
│
├── Backend-Framework
│ ├── python-fastapi-project-structuring/SKILL.md
│ ├── python-fastapi-routing-validation/SKILL.md
│ ├── python-fastapi-dependency-injection/SKILL.md
│ ├── python-fastapi-response-error-handling/SKILL.md
│ ├── python-fastapi-security-authentication/SKILL.md
│ ├── python-fastapi-security-attack-resistance/SKILL.md
│ ├── python-fastapi-api-testing/SKILL.md
│ └── python-fastapi-openapi-documentation/SKILL.md
│
├── Datenbank & Migrationen
│ ├── python-alembic-migrations/SKILL.md
│ └── python-alembic-migration-rebase/SKILL.md
│
├── Async-Muster
│ ├── python-asyncio/asyncio-concurrent-web-requests/SKILL.md
│ └── python-asyncio/asyncio-synchronization/SKILL.md
│
├── Konsolidierte Kern-Skills
│ ├── python-configuration-observability/SKILL.md (Konfiguration + Logging + Tracing)
│ ├── python-data-structures-type-system/SKILL.md (Sammlungen + Typen + Pydantic)
│ ├── python-lazy-evaluation-pipelines/SKILL.md (Generatoren + map/filter/reduce)
│ ├── python-higher-order-functools/SKILL.md (HOFs + Cache + partial + singledispatch)
│ ├── python-immutable-data-design/SKILL.md (NamedTuple + frozen DC + Kontextmanager)
│ └── python-concurrent-processing/SKILL.md (ProcessPool + asyncio-Integration)
│
├── Funktionale Programmierung (spezialisiert)
│ ├── python-functional-programming/python-decorator-design/SKILL.md
│ ├── python-functional-programming/python-functional-web-services/SKILL.md
│ ├── python-functional-programming/python-toolz-composition/SKILL.md
│ ├── python-functional-programming/python-itertools-combinatorics/SKILL.md
│ ├── python-functional-programming/python-recursion-tco/SKILL.md
│ └── python-functional-programming/python-pymonad-strict-evaluation/SKILL.md ← Opt-in
│
├── Bibliothekserstellung
│ ├── python-library-creation/SKILL.md
│ └── python-project-setup/SKILL.md
│
├── Polars
│ ├── python-polars/SKILL.md
│ └── python-polars-speedster/SKILL.md
│
├── DuckDB
│ └── python-duckdb-librarian/SKILL.md
│
├── Testen
│ ├── python-pytest/SKILL.md
│ └── python-pytest-property-based/SKILL.md
│
├── DevOps
│ ├── python-docker/SKILL.md
│ └── python-ci-cd/SKILL.md
│
└── Sicherheit
└── python-security/SKILL.md
Hinweis: Diese Skill sollte zuerst gelesen werden. Konsultiere die oben verlinkten spezifischen Skills für detaillierte Anleitungen zu jedem Bereich.