Under the Hood: FastAPI Ist Just Starlette + Pydantic
Grace Collins
Solutions Engineer · Leapcell

Starlette und Pydantic: Leistungsstarke APIs ohne FastAPI erstellen
Im Bereich der Python-Webentwicklung hat FastAPI aufgrund seiner prägnanten und benutzerfreundlichen Funktionen viel Aufmerksamkeit erhalten. In Wirklichkeit handelt es sich jedoch nur um eine High-Level-Kapselung von Starlette und Pydantic. Die offizielle Starlette-Website präsentiert ihre umfangreichen Funktionen, und Pydantic ist für seine leistungsstarken Datenvalidierungsfunktionen bekannt. Durch die direkte Verwendung dieser beiden Bibliotheken können Entwickler flexibel hochleistungsfähige APIs erstellen, ohne auf die Kapselung von FastAPI angewiesen zu sein. Im Folgenden werden wir dies detailliert erläutern, indem wir die Kernfunktionen und -merkmale beider Bibliotheken kombinieren.
1. Kernfunktionen von Starlette und Beispiele
1.1 Asynchrone Anfrageverarbeitung
Starlette basiert auf dem ASGI-Standard und kann asynchrone Aufgaben effizient verarbeiten. Ein Vergleich mit der Schreibweise in FastAPI kann die zugrunde liegende Logik besser widerspiegeln:
FastAPI Beispiel
from fastapi import FastAPI import asyncio # Erstellen Sie eine FastAPI-Anwendungsinstanz app = FastAPI() # Verwenden Sie einen Decorator, um eine GET-Anforderungsroute zu definieren. Die Funktion ist eine asynchrone Funktion und kann zeitaufwändige Operationen verarbeiten, ohne andere Anforderungen zu blockieren @app.get("/async_items/") async def async_read_items(): await asyncio.sleep(1) # Simulieren Sie eine I/O-Operation und pausieren Sie für 1 Sekunde return {"message": "FastAPI asynchrones Verarbeitungsbeispiel"}
Starlette Beispiel
from starlette.applications import Starlette from starlette.responses import JSONResponse import asyncio # Erstellen Sie eine Starlette-Anwendungsinstanz app = Starlette() # Definieren Sie die Route direkt auf der Anwendungsinstanz und geben Sie den Pfad und die Anforderungsmethode an. Die Bearbeitungsfunktion ist eine asynchrone Funktion @app.route("/async_items/", methods=["GET"]) async def async_read_items(request): await asyncio.sleep(1) # Simulieren Sie eine I/O-Operation und pausieren Sie für 1 Sekunde return JSONResponse({"message": "Starlette asynchrones Verarbeitungsbeispiel"})
Wie man sehen kann, vereinfacht FastAPI die Routendefinition durch Decorators, während Starlette näher an den nativen ASGI-Operationen ist. Es definiert Routen direkt auf der Anwendungsinstanz und bietet so mehr Flexibilität.
1.2 Verwendung von Middleware
Starlette unterstützt eine Vielzahl von Middleware. Zum Beispiel das Hinzufügen einer einfachen Logging-Middleware, die in FastAPI durch eine bestimmte Dependency Injection implementiert werden muss:
Starlette Middleware Beispiel
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.middleware.base import BaseHTTPMiddleware import logging # Konfigurieren Sie den Logger logger = logging.getLogger(__name__) # Benutzerdefinierte Logging-Middleware, die von BaseHTTPMiddleware erbt class LoggingMiddleware(BaseHTTPMiddleware): async def dispatch(self, request, call_next): # Protokollieren Sie die Anforderungsinformationen, einschließlich der Anforderungsmethode und URL logger.info(f"Request: {request.method} {request.url}") # Fahren Sie mit der Verarbeitung der Anforderung fort und holen Sie die Antwort ab response = await call_next(request) # Protokollieren Sie den Antwortstatuscode logger.info(f"Response: {response.status_code}") return response # Erstellen Sie eine Starlette-Anwendungsinstanz und übergeben Sie die Middleware-Instanz app = Starlette(middleware=[LoggingMiddleware(app)]) # Definieren Sie die Routenbearbeitungsfunktion @app.route("/middleware_example/", methods=["GET"]) async def middleware_example(request): return JSONResponse({"message": "Die Middleware ist wirksam"})
Um eine ähnliche Funktionalität in FastAPI zu erreichen, ist es erforderlich, sich auf benutzerdefinierte Abhängigkeitsfunktionen und globale Abhängigkeitskonfigurationen zu verlassen. Im Vergleich dazu ist die Verwendung von Middleware in Starlette intuitiver und näher an der zugrunde liegenden ASGI-Spezifikation.
1.3 WebSocket-Unterstützung
Starlette unterstützt nativ WebSocket. Hier ist ein einfaches Beispiel für einen WebSocket-Chat:
from starlette.applications import Starlette from starlette.websockets import WebSocket, WebSocketDisconnect import json # Erstellen Sie eine Starlette-Anwendungsinstanz app = Starlette() # Speichern Sie die WebSocket-Objekte der verbundenen Clients connected_clients = [] # Definieren Sie die WebSocket-Routenbearbeitungsfunktion @app.websocket_route("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() # Akzeptieren Sie die WebSocket-Verbindung connected_clients.append(websocket) # Fügen Sie den verbundenen Client zur Liste hinzu try: while True: # Empfangen Sie die vom Client gesendeten Textdaten data = await websocket.receive_text() message = json.loads(data) # Analysieren Sie die empfangene JSON-Zeichenkette in ein Python-Objekt for client in connected_clients: if client != websocket: # Leiten Sie die Nachricht an andere Clients außer dem Absender weiter await client.send_text(json.dumps(message)) except WebSocketDisconnect: connected_clients.remove(websocket) # Entfernen Sie den Client aus der Liste, wenn die Verbindung getrennt wird
Obwohl FastAPI auch WebSocket unterstützt, ähneln die Implementierungsdetails denen von Starlette. Starlette stellt die WebSocket-Verarbeitungsschnittstelle direkt zur Verfügung, was für Entwickler bequemer ist, um tiefgreifende Anpassungen vorzunehmen.
2. Anwendung von Pydantic in Starlette
2.1 Datenvalidierung und Serialisierung
Verwendung von Pydantic zur Datenvalidierung in Starlette im Vergleich zu FastAPI:
FastAPI Beispiel
from fastapi import FastAPI from pydantic import BaseModel # Erstellen Sie eine FastAPI-Anwendungsinstanz app = FastAPI() # Verwenden Sie Pydantic, um ein Datenmodell zur Validierung und Serialisierung von Daten zu definieren class Item(BaseModel): name: str price: float # Definieren Sie die Routenbearbeitungsfunktion. FastAPI validiert automatisch die eingehenden Daten und serialisiert die Antwort @app.post("/fastapi_items/") async def create_fastapi_item(item: Item): return item
Starlette Beispiel
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.requests import Request from pydantic import BaseModel # Erstellen Sie eine Starlette-Anwendungsinstanz app = Starlette() # Verwenden Sie Pydantic, um ein Datenmodell zur Validierung und Serialisierung von Daten zu definieren class Item(BaseModel): name: str price: float # Definieren Sie die Routenbearbeitungsfunktion und verarbeiten Sie die Anforderungsdaten und die Validierungslogik manuell @app.route("/starlette_items/", methods=["POST"]) async def create_starlette_item(request: Request): data = await request.json() # Holen Sie die JSON-Daten aus der Anforderung ab try: item = Item(**data) # Verwenden Sie Pydantic, um die Daten zu validieren. Wenn sie nicht gültig sind, wird eine Ausnahme ausgelöst except ValueError as e: return JSONResponse({"error": str(e)}, status_code=400) # Geben Sie eine Fehlermeldung zurück, wenn die Validierung fehlschlägt return JSONResponse(item.dict()) # Geben Sie die serialisierte Antwort zurück, wenn die Validierung erfolgreich ist
FastAPI verarbeitet automatisch die Datenvalidierung und die Fehlerrückgabe, während Entwickler in Starlette Ausnahmen manuell abfangen und verarbeiten müssen. Dieser Ansatz gibt Entwicklern jedoch auch mehr Kontrolle.
2.2 Komplexe Datenmodelle und verschachtelte Validierung
Beim Umgang mit komplexen Datenmodellen werden die Vorteile von Pydantic deutlicher:
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.requests import Request from pydantic import BaseModel # Erstellen Sie eine Starlette-Anwendungsinstanz app = Starlette() # Definieren Sie das Adressdatenmodell class Address(BaseModel): street: str city: str zip_code: str # Definieren Sie das Benutzerdatenmodell, das ein verschachteltes Adressmodell enthält class User(BaseModel): username: str email: str address: Address # Definieren Sie die Routenbearbeitungsfunktion, um die Validierung und Speicherung von Benutzerdaten zu verarbeiten @app.route("/users/", methods=["POST"]) async def create_user(request: Request): data = await request.json() # Holen Sie die JSON-Daten aus der Anforderung ab try: user = User(**data) # Verwenden Sie Pydantic, um die verschachtelten Daten zu validieren. Wenn sie nicht gültig sind, wird eine Ausnahme ausgelöst except ValueError as e: return JSONResponse({"error": str(e)}, status_code=400) # Geben Sie eine Fehlermeldung zurück, wenn die Validierung fehlschlägt return JSONResponse(user.dict()) # Geben Sie die serialisierte Antwort zurück, wenn die Validierung erfolgreich ist
Ob es sich um Starlette oder FastAPI handelt, Pydantic kann die Validierung verschachtelter Datenstrukturen effizient verarbeiten, um die Integrität und Genauigkeit der Daten zu gewährleisten.
3. Tiefe Integration von Starlette und Pydantic
Durch die Kombination des Routings und der Middleware von Starlette mit der Datenvalidierung von Pydantic können wir eine voll funktionsfähige API erstellen:
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.requests import Request from starlette.exceptions import HTTPException from starlette.middleware.cors import CORSMiddleware from pydantic import BaseModel # Erstellen Sie eine Starlette-Anwendungsinstanz app = Starlette() # Fügen Sie CORS-Middleware hinzu, um Anforderungen von allen Ursprüngen zuzulassen (in einer Produktionsumgebung sollten bestimmte Domainnamen eingeschränkt werden) app.add_middleware(CORSMiddleware, allow_origins=["*"]) # Verwenden Sie Pydantic, um das Produktdatenmodell zu definieren class Product(BaseModel): name: str price: float quantity: int # Liste zum Speichern von Produktdaten products = [] # Definieren Sie die Routenbearbeitungsfunktion zum Erstellen von Produkten @app.route("/products/", methods=["POST"]) async def create_product(request: Request): data = await request.json() # Holen Sie die JSON-Daten aus der Anforderung ab try: product = Product(**data) # Verwenden Sie Pydantic, um die Daten zu validieren. Wenn sie nicht gültig sind, wird eine Ausnahme ausgelöst except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) # Geben Sie eine HTTP-Ausnahme zurück, wenn die Validierung fehlschlägt products.append(product.dict()) # Fügen Sie die Produktdaten zur Liste hinzu, wenn die Validierung erfolgreich ist return JSONResponse(product.dict()) # Geben Sie die erstellten Produktdaten zurück # Definieren Sie die Routenbearbeitungsfunktion zum Abrufen aller Produkte @app.route("/products/", methods=["GET"]) async def get_products(request): return JSONResponse(products) # Geben Sie alle Produktdaten zurück
Dieses Beispiel demonstriert den vollständigen Prozess, in dem Starlette Routing, Cross-Origin-Probleme (durch Middleware) verarbeitet und Pydantic Datenvalidierung und -serialisierung durchführt. Im Vergleich zu FastAPI fehlen zwar Funktionen wie das automatische Generieren von Dokumentation, aber Entwickler können je nach Bedarf flexibel Bibliotheken von Drittanbietern zur Erweiterung auswählen, z. B. die Verwendung von drf-spectacular
oder apispec
zum Generieren von API-Dokumentation.
Fazit
Die Kombination von Starlette und Pydantic kann hochleistungsfähige und funktionsreiche APIs erstellen, ohne auf die Kapselung von FastAPI angewiesen zu sein. Starlette bietet eine flexible ASGI-Anwendungsgrundlage, die Kernfunktionen wie asynchrone Verarbeitung, Middleware und WebSocket unterstützt; Pydantic konzentriert sich auf Datenvalidierung und Serialisierung. Obwohl FastAPI den Entwicklungsprozess vereinfacht, ermöglicht die direkte Verwendung von Starlette und Pydantic Entwicklern, ein tieferes Verständnis der zugrunde liegenden Prinzipien zu erlangen, hochgradig angepasste Anpassungen an die Projektanforderungen vorzunehmen und in komplexen Szenarien eine stärkere Anpassungsfähigkeit zu zeigen.
Leapcell: Das Beste vom Serverlosen Webhosting
Abschließend möchte ich eine Plattform empfehlen, die sich am besten für die Bereitstellung von Python-Diensten eignet: Leapcell
🚀 Bauen Sie mit Ihrer Lieblingssprache
Entwickeln Sie mühelos in JavaScript, Python, Go oder Rust.
🌍 Stellen Sie unbegrenzt Projekte kostenlos bereit
Zahlen Sie nur für das, was Sie verbrauchen – keine Anfragen, keine Gebühren.
⚡ Pay-as-You-Go, keine versteckten Kosten
Keine Leerlaufgebühren, nur nahtlose Skalierbarkeit.
📖 Entdecken Sie unsere Dokumentation
🔹 Folgen Sie uns auf Twitter: @LeapcellHQ