Files
it-know-how/python/FastAPI.md
T
2026-03-27 12:58:01 +01:00

500 lines
14 KiB
Markdown
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Im Folgenden bekommst du eine umfassende, aber einsteigerfreundliche Einführung in FastAPI.
---
## 1. Grundidee: Was ist FastAPI?
**FastAPI** ist ein modernes, schnelles Web-Framework für Python, mit dem du **Web-APIs** (Schnittstellen) bauen kannst.
Eine API ist eine „Schnittstelle“, über die andere Programme mit deinem Programm sprechen können z.B. eine Web-App, ein Mobile-App-Backend oder interne Services in einem Unternehmen.
Kernpunkte von FastAPI:
- **Schwerpunkt:** Aufbau von **HTTP-APIs** (REST-APIs, JSON-basierte APIs).
- **Geschwindigkeit:** Sehr performant durch Nutzung von **asynchronem Python** (`async`/`await`), basierend auf **ASGI**.
- **Typisierung:** Starke Nutzung von **Python-Typannotationen** (z.B. `str`, `int`, eigene Klassen).
→ Daraus entstehen automatisch:
- Validierung von Daten,
- automatische Dokumentation (Swagger / OpenAPI),
- bessere IDE-Unterstützung (Autovervollständigung, Fehlererkennung).
- **Auto-Dokumentation:** FastAPI generiert automatisch eine **interaktive API-Dokumentation** im Browser.
Ein typisches „Hello World“ mit FastAPI sieht so aus:
```python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
```
Starten kannst du das z.B. mit:
```bash
uvicorn main:app --reload
```
Dann ist die API z.B. unter `http://127.0.0.1:8000` erreichbar.
---
## 2. Abgrenzung: FastAPI vs. verwandte Begriffe und Frameworks
### 2.1 FastAPI vs. „API“ / REST / HTTP allgemein
- **HTTP**: Das zugrunde liegende Protokoll, über das Browser oder andere Dienste kommunizieren.
- **REST-API**: Eine Art, HTTP-APIs zu strukturieren (z.B. `GET /users`, `POST /orders`).
- **FastAPI**: Ein **Framework**, das dir hilft, solche HTTP/REST-APIs in Python zu bauen.
FastAPI „spricht“ also HTTP, baut REST-APIs, ist aber selbst das **Werkzeug**, kein Protokoll.
---
### 2.2 FastAPI vs. Flask
**Flask** ist ein sehr bekanntes, minimalistisches Python-Webframework.
**Ähnlichkeiten:**
- Beide erlauben es, mit wenig Code HTTP-Endpunkte zu definieren.
- Beide sind relativ leichtgewichtig und flexibel.
**Unterschiede:**
- **Asynchronität**:
- Flask: traditionell synchron (WSGI), Async ist erst neuerdings und eingeschränkt verfügbar.
- FastAPI: von Anfang an für **async** gebaut (ASGI).
- **Typen & Validierung**:
- Flask: Kein eingebautes System für automatische Validierung du machst das selbst oder mit Erweiterungen.
- FastAPI: Nutzt **[[Pydantic]]**-Modelle und Typannotationen → automatische Validierung.
- **Dokumentation**:
- Flask: Kein automatisches API-Dokumentations-UI.
- FastAPI: Automatisch generierte OpenAPI/Swagger-UI unter `/docs` und `/redoc`.
Praxisbeispiel Vergleich:
**Flask:**
```python
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/items", methods=["POST"])
def create_item():
data = request.get_json()
name = data.get("name")
price = data.get("price")
if not isinstance(name, str) or not isinstance(price, (int, float)):
return jsonify({"error": "Invalid data"}), 400
return jsonify({"name": name, "price": price})
```
**FastAPI:**
```python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.post("/items")
def create_item(item: Item):
# item ist schon validiert
return item
```
FastAPI übernimmt hier die Validierung automatisch.
---
### 2.3 FastAPI vs. Django (und Django REST Framework)
**Django** ist ein „Full-Stack“-Framework:
- liefert Templates, ORM (Datenbankzugriff), Admin-Interface, Auth-System, Formulare etc.
- ideal für klassische Webanwendungen mit HTML-Seiten.
Für APIs nutzt man meist **Django REST Framework (DRF)** als Erweiterung.
**FastAPI** dagegen ist:
- stärker auf **APIs** fokussiert,
- nicht „alles aus einer Hand“, sondern:
- Web-Layer: `Starlette`,
- Datenvalidierung: `Pydantic`,
- Datenbank: du wählst selbst z.B. SQLAlchemy, Tortoise ORM etc.
Faustregel:
- Wenn du eine klassische Website mit HTML-Rendering brauchst → Django.
- Wenn du primär eine performant API bauen willst (z.B. für SPA, Microservices) → FastAPI ist sehr attraktiv.
---
### 2.4 FastAPI vs. Node.js / Express
**Node.js + Express** ist eine sehr verbreitete Lösung für APIs in JavaScript/TypeScript.
- **Sprache:** Node → JavaScript/TypeScript, FastAPI → Python.
- **Typen:** TypeScript kann Typen bieten, FastAPI nutzt Python-Typen + [[Pydantic]].
- **Ökosystem:** Node sehr stark im Web-/Frontend-nahen Bereich, Python stark bei Data Science, Machine Learning und Backend-Services.
FastAPI ist besonders interessant, wenn du sowieso Python nutzt (z.B. wegen ML/AI) und dafür eine passende Web-API brauchst.
---
## 3. Welche Probleme löst FastAPI?
### 3.1 Saubere, valide Eingabedaten
Problem ohne Framework-Unterstützung:
- Du bekommst z.B. einen JSON-Body und musst:
- alle Felder prüfen (Typ, Pflichtfelder, Wertebereiche),
- Fehler verständlich zurückgeben,
- alles manuell machen.
FastAPI + [[Pydantic]] lösen das:
```python
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class User(BaseModel):
name: str = Field(..., min_length=3)
age: int = Field(..., ge=0, le=120) # 0 <= age <= 120
@app.post("/users")
def create_user(user: User):
# Wenn name zu kurz oder age negativ ist, liefert FastAPI automatisch 422 mit Fehlerdetails
return {"message": "User created", "user": user}
```
Vorteil:
- Weniger Fehleranfälligkeit.
- Konsistente Fehlerantworten.
- Gute Developer-Erfahrung.
---
### 3.2 Automatische Dokumentation und Testbarkeit
FastAPI erzeugt automatisch eine OpenAPI-Spezifikation und UI:
- `http://localhost:8000/docs` → Swagger UI (interaktive Oberfläche, du kannst Requests direkt aus dem Browser abschicken).
- `http://localhost:8000/redoc` → ReDoc, alternative Dokumentationsansicht.
Das hilft:
- Dir selbst beim Testen.
- Frontend-Entwicklern oder anderen Teams, die deine API nutzen.
- Beim automatisierten Generieren von Client-SDKs (z.B. TypeScript-Client).
---
### 3.3 Performance und asynchrones I/O
Problem:
- In „klassischen“ synchronen Webframeworks blockiert jeder Request, der z.B. auf eine externe API oder langsame DB wartet.
- Bei vielen gleichzeitigen Anfragen leiden Durchsatz und Antwortzeit.
FastAPI setzt auf **ASGI** (Asynchronous Server Gateway Interface) und `async def`:
```python
from fastapi import FastAPI
import httpx # asynchroner HTTP-Client
app = FastAPI()
@app.get("/external")
async def call_external_api():
async with httpx.AsyncClient() as client:
response = await client.get("https://httpbin.org/get")
return response.json()
```
Vorteil:
- Viele I/O-lastige Requests können parallel abgewickelt werden.
- Besonders sinnvoll bei Microservices, die viel mit anderen Services kommunizieren.
---
### 3.4 Abhängigkeiten und Wiederverwendbarkeit (Dependency Injection)
FastAPI bietet ein eingebautes **Dependency Injection**-System.
Beim Entwickeln von APIs brauchst du häufig:
- Datenbankverbindungen,
- Authentifizierungslogik,
- Konfigurationsobjekte.
Ohne System würdest du das überall wiederholen oder global speichern.
Mit FastAPI:
```python
from fastapi import Depends, FastAPI
app = FastAPI()
def get_settings():
# z. B. Konfiguration laden
return {"app_name": "Meine App"}
@app.get("/info")
def read_info(settings = Depends(get_settings)):
return {"app_name": settings["app_name"]}
```
Das verbessert:
- Testbarkeit (du kannst Dependencies im Test austauschen),
- Struktur deines Codes (klarere Trennung von Zuständigkeiten).
---
## 4. Typische Einsatzszenarien (praxisnah)
### Beispiel 1: Einfaches CRUD für ein „Item“
```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List
app = FastAPI()
class Item(BaseModel):
id: int
name: str
price: float
# „Fake-Datenbank“ im Speicher
items_db: List[Item] = []
@app.post("/items", response_model=Item)
def create_item(item: Item):
# einfache Prüfung: ID darf nicht doppelt sein
if any(existing.id == item.id for existing in items_db):
raise HTTPException(status_code=400, detail="Item ID already exists")
items_db.append(item)
return item
@app.get("/items", response_model=List[Item])
def list_items():
return items_db
@app.get("/items/{item_id}", response_model=Item)
def get_item(item_id: int):
for item in items_db:
if item.id == item_id:
return item
raise HTTPException(status_code=404, detail="Item not found")
```
Du bekommst:
- JSON-APIs für CRUD,
- automatische Dokumentation,
- automatische Validierung für `Item`.
---
### Beispiel 2: Path-Parameter, Query-Parameter, Body
```python
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class SearchFilters(BaseModel):
min_price: Optional[float] = None
max_price: Optional[float] = None
@app.get("/products/{category}")
def search_products(
category: str,
q: Optional[str] = None, # Query-Parameter ?q=Text
filters: SearchFilters = None # Body JSON
):
return {
"category": category,
"query": q,
"filters": filters
}
```
Beispiel-Request:
- `GET /products/books?q=python` mit JSON-Body:
```json
{
"min_price": 10,
"max_price": 50
}
```
FastAPI erkennt:
- `category` als Pfadparameter,
- `q` als Query-Parameter,
- `filters` als JSON-Body und validiert ihn.
---
### Beispiel 3: Einfache Authentifizierung per Token
```python
from fastapi import Depends, FastAPI, HTTPException, Header
app = FastAPI()
def get_current_user(x_token: str = Header(...)):
if x_token != "secrettoken123":
raise HTTPException(status_code=401, detail="Invalid or missing token")
return {"username": "alice"}
@app.get("/profile")
def read_profile(current_user = Depends(get_current_user)):
return {"message": f"Hello, {current_user['username']}"}
```
Hier:
- Der Endpunkt `/profile` verlangt einen HTTP-Header `X-Token`.
- FastAPI übernimmt das Zusammenspiel von Header → Dependency → Endpoint-Logik.
---
## 5. Herausforderungen und typische Stolpersteine
FastAPI nimmt dir viel ab, aber es gibt einige Themen, die für Einsteiger Hürden sein können:
### 5.1 Asynchrones Programmieren (`async` / `await`)
- Wenn du noch nie mit Async gearbeitet hast, ist es ungewohnt:
- Wann nutze ich `async def`?
- Wo brauche ich `await`?
- Was ist „Blocking I/O“?
- Du musst darauf achten, dass du **asynchrone Bibliotheken** verwendest, wenn du im Handler `async` einsetzt
(z.B. `httpx` statt `requests`, `asyncpg` statt `psycopg2`).
Wenn du erst mal einsteigst, kannst du auch erst **synchron** (ohne `async`) starten und später umstellen.
---
### 5.2 Typannotationen und Pydantic verstehen
FastAPI baut stark auf Typen auf:
- Für jemanden ohne Erfahrung mit Typannotationen in Python ist das anfangs ungewohnt.
- Du musst verstehen:
- Wie du eigene Modelle mit `BaseModel` definierst.
- Wie optionale Felder mit `Optional[...]` und Standardwerten funktionieren.
- Wie Validierung und Fehlernachrichten von [[Pydantic]] aussehen.
Aber:
Der Lerneffekt lohnt sich, weil du insgesamt saubereren, stabileren Code bekommst.
---
### 5.3 Datenbankintegration
FastAPI selbst bringt keinen [[ORM]] mit. Du musst wählen:
- z.B. **[[SQLAlchemy]]**, Tortoise-ORM, Prisma, Gino etc.
Dabei stellen sich Fragen wie:
- Wie verwalte ich Datenbank-Sessions pro Request?
- Nutze ich die sync- oder async-Variante meiner ORM?
- Wie realisiere ich Migrations (alembic, etc.)?
Es gibt viele Beispielprojekte, aber es ist ein zusätzlicher Schritt im Vergleich zu Django, wo ein [[ORM]] „eingebaut“ ist.
---
### 5.4 Deployment / Betrieb
Für Einsteiger ist der Weg von „läuft lokal“ zu „läuft im Internet“ oft herausfordernd:
- FastAPI-Anwendung läuft typischerweise mit:
- [[uvicorn]] oder [[hypercorn]] (ASGI-Server),
- oft hinter einem Reverse Proxy wie [[Nginx]].
- Themen:
- Logging konfigurieren,
- Umgebungsvariablen (Konfiguration),
- HTTPS/SSL (z.B. via [[Nginx]]/Lets Encrypt),
- Skalierung (mehrere Worker, z.B. `gunicorn` + `uvicorn.workers.UvicornWorker`).
Für den Anfang kannst du auch auf Plattformen wie Render, Railway, fly.io, oder Docker + Cloud setzen.
---
### 5.5 Versionierung und Wartung großer Projekte
Bei größeren APIs:
- Wie strukturiere ich meinen Code?
- z.B. mit **Routern** (`APIRouter`) und Modulen.
- Wie versioniere ich die API? (`/v1/user`, `/v2/user`, …)
- Wie halte ich die Dokumentation aktuell?
- FastAPI hilft zwar, aber bei vielen Endpunkten braucht man Konventionen und ggf. zusätzliche Dokumentation.
Beispiel mit Router:
```python
from fastapi import FastAPI, APIRouter
app = FastAPI()
items_router = APIRouter(prefix="/items", tags=["items"])
@items_router.get("/")
def list_items():
return [{"id": 1, "name": "Item 1"}]
app.include_router(items_router)
```
So kannst du größere Projekte modular strukturieren.
---
## 6. Zusammenfassung
- **FastAPI** ist ein modernes Framework für **Web-APIs in Python**, fokussiert auf:
- hohe **Performance** (async),
- **Typen** + automatische Validierung ([[Pydantic]]),
- automatische **OpenAPI-/Swagger-Dokumentation**,
- gute Developer Experience.
- Es unterscheidet sich von:
- **Flask**: moderner, stärker typisiert, async-first, integrierte Validierung & Doku.
- **Django**: kein Full-Stack-Framework, sondern eher API-fokussiert; du kombinierst es mit eigenen Tools für DB, Templates etc.
- Node/Express: andere Sprache, andere Ökosysteme; FastAPI besonders stark, wenn du ohnehin Python nutzt.
- Es löst typische Probleme beim API-Bau:
- Validierung von Eingaben,
- Dokumentation & Testbarkeit,
- Performance bei vielen gleichzeitigen Anfragen,
- saubere Struktur durch Dependency Injection.
- Herausforderungen:
- Einstieg in asynchrones Programmieren,
- Verständnis von Typannotationen & [[Pydantic]],
- separate Auswahl & Integration einer Datenbanklösung,
- Deployment & Betrieb.