Use Cases (Aktualisiert: 2.6.2026)

Python mit Claude Code: Praxisguide für uv, pytest, Ruff und FastAPI

Baue ein prüfbares Python-Projekt mit Claude Code, uv, pyproject.toml, pytest, Ruff, FastAPI und sicherer Iteration.

Python mit Claude Code: Praxisguide für uv, pytest, Ruff und FastAPI

Bei Python mit Claude Code ist der erste generierte Code selten das eigentliche Problem. Schwieriger ist die Frage, ob das Projekt wirklich gesund ist: Ist die Umgebung reproduzierbar, funktionieren die Imports, laufen Tests, ist das Format konsistent und kann die nächste Änderung sauber geprüft werden?

Dieser Guide zeigt einen kleinen, anfängerfreundlichen Ablauf. Wir verwenden uv oder das eingebaute venv, sammeln Projektregeln in pyproject.toml, bauen eine minimale FastAPI-App, ergänzen optional eine CLI, schreiben Tests mit pytest und prüfen den Code mit ruff. Claude Code arbeitet dabei in einem klaren Rahmen statt eine große Architektur zu erraten.

Nutze primäre Dokumentation: Claude Code, Python Packaging zum Schreiben von pyproject.toml, uv Installation, pytest Einstieg, Ruff und FastAPI First Steps.

Erst ein kleines Ziel definieren

Bitte Claude Code am Anfang nicht gleichzeitig um Authentifizierung, Datenbank, Docker, CI und Hintergrundjobs. Für den ersten Schritt reicht ein Ergebnis, das jeder prüfen kann.

  • uv run pytest läuft erfolgreich
  • uv run ruff check . und uv run ruff format . laufen
  • FastAPI kann eine Aufgabe erstellen und auflisten
  • Die CLI kann eine Aufgabe im Terminal hinzufügen
  • Claude Code meldet die ausgeführten Befehle
flowchart LR
  A["Arbeitsbrief"] --> B["uv oder venv"]
  B --> C["pyproject.toml"]
  C --> D["Implementierung in src"]
  D --> E["pytest"]
  E --> F["ruff"]
  F --> G["Kleine Claude-Code-Iteration"]

Der Arbeitsbrief ist die Aufgabenbeschreibung für den Coding-Agenten. Er nennt Ziel, erlaubte Dateien, Python-Version und Prüfbefehle. Für dauerhafte Repository-Regeln lohnt sich zusätzlich CLAUDE.md Best Practices. Wenn die API größer wird, lies API-Entwicklung mit Claude Code und Teststrategien.

Der erste Prompt

Dieser Prompt ist bewusst konkret und begrenzt.

Füge diesem Repository eine kleine Task-Management-API für Python 3.12 hinzu.

Bedingungen:
- Nutze uv für Abhängigkeiten und sammle Einstellungen in pyproject.toml.
- Lege Code unter src/task_api/ und Tests unter tests/ ab.
- Implementiere POST /tasks und GET /tasks mit FastAPI.
- Schreibe pytest-Tests für den Erfolgsfall und einen 404-Fall.
- ruff check und ruff format müssen laufen.
- Zeige vor dem Editieren den Plan und berichte danach die ausgeführten Befehle.

Erlaubte Dateien:
- pyproject.toml
- src/task_api/**
- tests/**

So wird Claude Code zu einem Umsetzungspartner mit Nachweis, nicht nur zu einem Generator. Wenn die Änderung andere Ordner berührt oder keine Tests ausführt, ist der Fehler im Review sofort sichtbar.

Umgebung mit uv oder venv

Für neue Lernprojekte ist uv praktisch, weil es schnell ist und kurze Befehle bietet. Wenn auf einem Firmenrechner keine neuen Tools installiert werden dürfen, funktioniert venv genauso. Wichtig ist, die gewählte Methode nicht zu mischen.

macOS oder Linux:

mkdir task-api
cd task-api
uv init --app --python 3.12
uv add "fastapi[standard]"
uv add --dev pytest ruff
mkdir -p src/task_api tests
touch src/task_api/__init__.py

Windows PowerShell:

mkdir task-api
cd task-api
uv init --app --python 3.12
uv add "fastapi[standard]"
uv add --dev pytest ruff
New-Item -ItemType Directory -Force src/task_api, tests
New-Item -ItemType File -Force src/task_api/__init__.py

Fallback mit venv:

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install "fastapi[standard]" pytest ruff
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install "fastapi[standard]" pytest ruff

pyproject.toml zentral halten

Für Anfänger ist es verwirrend, wenn Abhängigkeiten, Testpfade und Lint-Regeln in mehreren Dateien liegen. Diese Version bündelt die wichtigsten Regeln.

[project]
name = "task-api"
version = "0.1.0"
description = "Small FastAPI and CLI sample for Claude Code practice"
requires-python = ">=3.11"
dependencies = [
  "fastapi[standard]>=0.115.0",
]

[project.scripts]
task-api = "task_api.cli:main"

[dependency-groups]
dev = [
  "pytest>=8.0.0",
  "ruff>=0.8.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/task_api"]

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]

[tool.ruff]
line-length = 100
target-version = "py311"

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP"]

FastAPI und CLI implementieren

Lege diesen Code in src/task_api/main.py ab. Die Speicherung im Speicher ist kein Produktionsdesign, aber ideal zum Lernen von Routing, Validierung, Antwortmodellen und Fehlern.

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field

app = FastAPI(title="Task API")


class TaskCreate(BaseModel):
    title: str = Field(min_length=1, max_length=80)


class Task(BaseModel):
    id: int
    title: str
    done: bool = False


_tasks: dict[int, Task] = {}
_next_id = 1


@app.post("/tasks", response_model=Task, status_code=201)
def create_task(payload: TaskCreate) -> Task:
    global _next_id
    task = Task(id=_next_id, title=payload.title)
    _tasks[task.id] = task
    _next_id += 1
    return task


@app.get("/tasks", response_model=list[Task])
def list_tasks() -> list[Task]:
    return list(_tasks.values())


@app.patch("/tasks/{task_id}/done", response_model=Task)
def mark_done(task_id: int) -> Task:
    task = _tasks.get(task_id)
    if task is None:
        raise HTTPException(status_code=404, detail="Task not found")
    updated = task.model_copy(update={"done": True})
    _tasks[task_id] = updated
    return updated
uv run fastapi dev src/task_api/main.py

Für eine CLI erstelle src/task_api/cli.py.

import argparse
import json
from pathlib import Path

DB_PATH = Path("tasks.json")


def load_tasks() -> list[dict[str, object]]:
    if not DB_PATH.exists():
        return []
    return json.loads(DB_PATH.read_text(encoding="utf-8"))


def save_tasks(tasks: list[dict[str, object]]) -> None:
    DB_PATH.write_text(json.dumps(tasks, ensure_ascii=False, indent=2), encoding="utf-8")


def add_task(title: str) -> dict[str, object]:
    tasks = load_tasks()
    task = {"id": len(tasks) + 1, "title": title, "done": False}
    tasks.append(task)
    save_tasks(tasks)
    return task


def main() -> None:
    parser = argparse.ArgumentParser(description="Task CLI")
    subparsers = parser.add_subparsers(dest="command", required=True)
    add_parser = subparsers.add_parser("add")
    add_parser.add_argument("title")
    args = parser.parse_args()
    if args.command == "add":
        task = add_task(args.title)
        print(f"Added #{task['id']}: {task['title']}")


if __name__ == "__main__":
    main()
uv run task-api add "write pytest"

Mit pytest und Ruff absichern

Erstelle tests/test_main.py und nutze die gleichen Prüfungen nach jeder Änderung.

import pytest
from fastapi.testclient import TestClient

from task_api import main
from task_api.main import app


@pytest.fixture(autouse=True)
def clean_tasks() -> None:
    main._tasks.clear()
    main._next_id = 1


def test_create_and_list_tasks() -> None:
    client = TestClient(app)
    response = client.post("/tasks", json={"title": "Write pytest"})
    assert response.status_code == 201
    assert response.json()["title"] == "Write pytest"
    list_response = client.get("/tasks")
    assert list_response.status_code == 200
    assert len(list_response.json()) == 1


def test_mark_done_returns_404_for_missing_task() -> None:
    client = TestClient(app)
    response = client.patch("/tasks/999/done")
    assert response.status_code == 404
    assert response.json()["detail"] == "Task not found"
uv run pytest
uv run ruff check .
uv run ruff format .

Praktische Anwendungsfälle

Erstens eignet sich der Ablauf für eine Lern-API: Routing, Pydantic, OpenAPI, Tests und Formatierung bleiben sichtbar. Zweitens passt er zu kleinen Business-CLIs, etwa CSV-Bereinigung, Dateiumbenennung oder Wochenreports. Drittens hilft er bei Legacy-Python, indem Claude Code zuerst bestehendes Verhalten mit Tests fixiert. Viertens ist er eine gute Basis für Team-Training.

Für wiederkehrende Briefs und Review-Muster passen Claude Code Produkte. Für Teams mit echten Repositories, Onboarding und Review-Regeln ist Training und Beratung der bessere nächste Schritt.

Typische Fehler

Der Paketmanager darf nicht offen bleiben, sonst mischen sich pip, poetry, uv und requirements.txt. Baue Datenbank und JWT nicht vor dem lauffähigen In-Memory-Beispiel ein. Prüfe Ruff-Diffs vor der Übernahme. Achte bei src-Layout auf pythonpath = ["src"] oder korrekte Paketinstallation. Und füge nie echte Secrets, Kundendaten oder Produktions-URLs in den Prompt ein.

Verifiziertes Ergebnis

Für diese Überarbeitung habe ich die Reihenfolge genutzt, die Masa für Python-Einsteigerunterlagen verwendet: Umgebung fixieren, pyproject.toml zentralisieren, FastAPI klein halten, Tests vor neuen Funktionen schreiben und Ruff täglich ausführen. Das macht Fehler lokalisierbar und Claude Code nützlich für Lernen, Review und Beratung.

#Claude Code #Python #uv #pytest #FastAPI
Kostenlos

Kostenloses PDF: Claude-Code-Cheatsheet

E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.

Wir schützen Ihre Daten und senden keinen Spam.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.