FastAPI: Framework web Python moderno ad alte prestazioni

Costruisci API estremamente veloci con documentazione automatica e sicurezza dei tipi

Indice

FastAPI è emerso come uno dei framework web più eccitanti per la creazione di API in Python, combinando funzionalità moderne di Python con prestazioni eccezionali e un’esperienza di sviluppo ottima.

Indipendentemente dal fatto che stiate costruendo microservizi, funzioni serverless o applicazioni web complesse, FastAPI fornisce gli strumenti necessari per API pronte per la produzione.

python e fastapi castello

Cosa è FastAPI?

FastAPI è un framework web moderno e ad alte prestazioni per la creazione di API con Python 3.8+ basato sugli hint di tipo standard di Python. Creato da Sebastián Ramírez, è stato progettato per essere facile da usare, veloce da codificare e pronto per la produzione fin dall’inizio.

Il framework si basa su due potenti librerie:

  • Starlette per il routing web e le capacità asincrone
  • Pydantic per la validazione dei dati utilizzando gli hint di tipo di Python

Questa combinazione fornisce prestazioni paragonabili a quelle di Node.js e Go mantenendo la semplicità e la leggibilità di Python. FastAPI ha guadagnato rapidamente popolarità, con migliaia di stelle su GitHub e adozione da parte di grandi aziende in tutto il mondo.

Funzionalità chiave che distinguono FastAPI

1. Documentazione API automatica

Una delle funzionalità più apprezzate di FastAPI è la documentazione API automatica e interattiva. Basata sullo standard OpenAPI (ex Swagger), FastAPI genera due interfacce di documentazione:

  • Swagger UI a /docs - Documentazione interattiva dove puoi testare direttamente gli endpoint API nel browser
  • ReDoc a /redoc - Alternativa con un design pulito a tre pannelli

La documentazione viene generata automaticamente dagli hint di tipo e dalle docstring del tuo codice, senza richiedere alcuna configurazione aggiuntiva. Questo significa che la tua documentazione è sempre aggiornata con il tuo codice.

2. Hint di tipo e validazione

FastAPI sfrutta gli hint di tipo di Python non solo per la documentazione ma anche per la validazione in fase di esecuzione e la serializzazione. Quando definisci un parametro di un endpoint come int, FastAPI automaticamente:

  • Verifica che la richiesta contenga un intero
  • Converte il valore dalla stringa all’intero
  • Restituisce messaggi di errore chiari se la validazione fallisce
  • Documenta il tipo del parametro nella documentazione API
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    username: str
    email: str
    age: int

@app.post("/users/")
async def create_user(user: User):
    return {"message": f"Utente {user.username} creato con successo"}

Questo approccio cattura i bug presto, riduce il codice boilerplate e rende il tuo API auto-documented.

3. Supporto asincrono

FastAPI è costruito su ASGI (Asynchronous Server Gateway Interface) invece che su WSGI, fornendo supporto nativo per async/await. Questo è cruciale per le applicazioni ad alte prestazioni che effettuano molte chiamate I/O (query al database, richieste API, operazioni su file).

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    # Le operazioni asincrone non bloccano altre richieste
    data = await fetch_from_database(item_id)
    return data

Il supporto asincrono significa che FastAPI può gestire migliaia di connessioni concorrenti in modo efficiente, rendendolo ideale per applicazioni cloud moderne e architetture di microservizi.

4. Prestazioni

FastAPI è uno dei framework Python più veloci disponibili, con prestazioni paragonabili a quelle dei framework Node.js e Go. Benchmark indipendenti mostrano costantemente che FastAPI supera i framework tradizionali come Flask e Django in modo significativo, soprattutto per i carichi di lavoro I/O-bound.

La velocità proviene da:

  • La validazione a livello C di Pydantic
  • L’implementazione efficiente asincrona di Starlette
  • L’assenza di overhead nel framework stesso

Iniziare con FastAPI

L’installazione di FastAPI è semplice. Quando si lavora con progetti Python, avere un gestore dei pacchetti Python rende la gestione delle dipendenze molto più semplice.avrai bisogno di FastAPI e di un server ASGI come Uvicorn:

pip install fastapi uvicorn[standard]

Ecco un’applicazione FastAPI minimale:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Ciao Mondo"}

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}

Esegui con:

uvicorn main:app --reload

Visita http://localhost:8000/docs per vedere la tua documentazione API interattiva.

Costruire API pronte per la produzione

Modelli di richiesta e risposta

Definire modelli di dati chiari è essenziale per API mantenibili. Seguire pattern di progettazione Python per l’architettura pulita aiuta a creare applicazioni ben strutturate:

from pydantic import BaseModel, EmailStr, Field
from typing import Optional
from datetime import datetime

class UserCreate(BaseModel):
    username: str = Field(..., min_length=3, max_length=50)
    email: EmailStr
    password: str = Field(..., min_length=8)

class UserResponse(BaseModel):
    id: int
    username: str
    email: str
    created_at: datetime
    
    class Config:
        orm_mode = True  # Consente a Pydantic di lavorare con oggetti ORM

@app.post("/users/", response_model=UserResponse)
async def create_user(user: UserCreate):
    # La tua logica aziendale qui
    new_user = save_user_to_database(user)
    return new_user

Il parametro response_model assicura che FastAPI restituisca solo i campi specificati, filtrando automaticamente dati sensibili come le password.

Iniezione di dipendenze

Il sistema di iniezione di dipendenze di FastAPI è potente ed elegante. Consente di:

  • Condividere codice tra gli endpoint
  • Imporre autenticazione/autorizzazione
  • Gestire connessioni al database
  • Gestire dipendenze complesse
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

async def get_current_user(token: str = Depends(oauth2_scheme)):
    user = verify_token(token)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Credenziali di autenticazione non valide"
        )
    return user

@app.get("/users/me")
async def read_users_me(current_user: User = Depends(get_current_user)):
    return current_user

Gestione degli errori

FastAPI fornisce gestori di eccezioni predefiniti e consente risposte personalizzate agli errori:

from fastapi import HTTPException

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    if item_id not in items_db:
        raise HTTPException(
            status_code=404,
            detail="Elemento non trovato",
            headers={"X-Error": "Intestazione personalizzata"}
        )
    return items_db[item_id]

Task di background

Per operazioni che non devono completarsi prima di restituire una risposta:

from fastapi import BackgroundTasks

def send_email_notification(email: str, message: str):
    # Logica per inviare email
    pass

@app.post("/send-notification/")
async def send_notification(
    email: str,
    background_tasks: BackgroundTasks
):
    background_tasks.add_task(send_email_notification, email, "Benvenuto!")
    return {"message": "Notifica programmata"}

Test delle applicazioni FastAPI

I test completi di unit testing in Python sono cruciali per API affidabili. FastAPI funziona senza problemi con pytest e fornisce un client di test:

from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Ciao Mondo"}

def test_read_item():
    response = client.get("/items/42?q=test")
    assert response.status_code == 200
    assert response.json() == {"item_id": 42, "q": "test"}

Per testare gli endpoint asincroni:

import pytest
from httpx import AsyncClient

@pytest.mark.asyncio
async def test_async_endpoint():
    async with AsyncClient(app=app, base_url="http://test") as ac:
        response = await ac.get("/")
    assert response.status_code == 200

Integrazione con il database

FastAPI funziona bene con diversi database e ORMs. Ecco un esempio con SQLAlchemy:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
from fastapi import Depends

DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(bind=engine)
Base = declarative_base()

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    username = Column(String, unique=True, index=True)
    email = Column(String, unique=True)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/users/{user_id}")
async def read_user(user_id: int, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="Utente non trovato")
    return user

Opzioni di distribuzione

Distribuzione con Docker

Le applicazioni FastAPI si containerizzano facilmente. Ecco un Dockerfile pronto per la produzione:

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Distribuzione su AWS Lambda

FastAPI funziona eccezionalmente bene con piattaforme serverless. Quando si costruisce un AWS Lambda a doppio modo con Python e Terraform, è possibile distribuire le applicazioni FastAPI utilizzando Mangum, un adattatore che avvolge FastAPI per AWS Lambda:

from mangum import Mangum
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Ciao da Lambda!"}

handler = Mangum(app)

Per distribuzioni più complesse, AWS SAM con Python PowerTools fornisce strumenti eccellenti per le applicazioni FastAPI.

Distribuzione su server tradizionali

Per la distribuzione su server tradizionali o Kubernetes:

# Con Gunicorn e worker Uvicorn
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000

Funzionalità avanzate

CORS (Condivisione risorse tra origini)

Abilita CORS per le applicazioni frontend:

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://example.com"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Supporto WebSocket

FastAPI supporta WebSocket per la comunicazione in tempo reale:

from fastapi import WebSocket

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Messaggio ricevuto: {data}")

Integrazione con GraphQL

FastAPI può lavorare con GraphQL tramite Strawberry o altre librerie GraphQL:

import strawberry
from strawberry.fastapi import GraphQLRouter

@strawberry.type
class Query:
    @strawberry.field
    def hello(self) -> str:
        return "Ciao Mondo"

schema = strawberry.Schema(query=Query)
graphql_app = GraphQLRouter(schema)

app.include_router(graphql_app, prefix="/graphql")

Lavorare con LLM e AI

FastAPI è eccellente per costruire API alimentate dall’AI. Quando si vincolano gli LLM con output strutturato utilizzando Ollama, i modelli Pydantic di FastAPI forniscono definizioni di schema perfette per le risposte strutturate:

from pydantic import BaseModel
from typing import List
import httpx

class SentimentResponse(BaseModel):
    sentiment: str
    confidence: float
    keywords: List[str]

@app.post("/analyze-sentiment/", response_model=SentimentResponse)
async def analyze_sentiment(text: str):
    # Chiama il servizio LLM
    async with httpx.AsyncClient() as client:
        response = await client.post(
            "http://localhost:11434/api/generate",
            json={
                "model": "qwen2.5",
                "prompt": f"Analisi del sentiment: {text}",
                "format": SentimentResponse.schema_json()
            }
        )
    return response.json()

Migliori pratiche e consigli

1. Utilizzare in modo coerente i decoratori delle operazioni di percorso

Organizza i tuoi endpoint con metodi HTTP chiari:

@app.get("/items/")      # Elenco elementi
@app.post("/items/")     # Crea elemento
@app.get("/items/{id}")  # Ottieni elemento specifico
@app.put("/items/{id}")  # Aggiorna elemento
@app.delete("/items/{id}") # Elimina elemento

2. Versiona la tua API

Includi la versione dell’API fin dall’inizio:

from fastapi import APIRouter

api_v1 = APIRouter(prefix="/api/v1")
api_v2 = APIRouter(prefix="/api/v2")

@api_v1.get("/users/")
async def get_users_v1():
    return {"version": "1.0"}

app.include_router(api_v1)
app.include_router(api_v2)

3. Usa le variabili d’ambiente

Non codificare mai segreti. Usa le variabili d’ambiente:

from pydantic import BaseSettings

class Settings(BaseSettings):
    database_url: str
    secret_key: str
    api_key: str
    
    class Config:
        env_file = ".env"

settings = Settings()

4. Implementa il logging corretto

Utilizza il modulo logging di Python:

import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@app.get("/items/")
async def get_items():
    logger.info("Recupero tutti gli elementi")
    return items

5. Monitora le prestazioni

Utilizza middleware per il timing delle richieste:

import time
from fastapi import Request

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response

FastAPI vs Altri Framework

FastAPI vs Flask

Flask è più minimalista e ti dà più controllo, ma FastAPI fornisce più funzionalità predefinite:

  • FastAPI ha validazione e documentazione automatica
  • Flask richiede estensioni per il supporto asincrono
  • FastAPI è significativamente più veloce per i carichi di lavoro I/O-bound
  • Flask ha un ecosistema più grande e più risorse di apprendimento

FastAPI vs Django REST Framework

Django REST Framework (DRF) fa parte dell’ecosistema più grande di Django:

  • DRF include un ORM completo e un’interfaccia amministrativa
  • FastAPI è più leggero e più veloce
  • DRF è migliore per applicazioni complesse e pesanti dal punto di vista del database
  • FastAPI eccelle in microservizi e API autonome

FastAPI vs Node.js/Express

FastAPI offre la semplicità di Python con prestazioni paragonabili a quelle di Node.js:

  • Prestazioni asincrone simili
  • Il sistema di tipo di Python è più robusto rispetto a JavaScript/TypeScript
  • Node.js ha un ecosistema di pacchetti più grande
  • La documentazione automatica di FastAPI è superiore

Caso d’uso reale

Architettura a microservizi

La natura leggera di FastAPI e il tempo di avvio rapido lo rendono ideale per i microservizi. Ogni servizio può essere distribuito e scalato in modo indipendente.

API per l’apprendimento automatico

Servire modelli di apprendimento automatico è un caso d’uso comune per FastAPI. Il supporto asincrono del framework gestisce efficientemente molte richieste di previsione.

Backend per applicazioni mobile/web

FastAPI è un eccellente backend per le moderne applicazioni SPA (Single Page Applications) e mobile grazie alla gestione automatica di CORS e al supporto WebSocket.

Raccolta dati IoT

FastAPI può gestire l’ingestione di grandi quantità di dati da dispositivi IoT, elaborando e archiviano i dati dei sensori in modo efficiente.

Chatbot e AI conversazionale

Costruire interfacce conversazionali e backend per chatbot beneficia del supporto WebSocket e delle capacità asincrone di FastAPI.

Errori comuni e soluzioni

1. Operazioni bloccanti in funzioni asincrone

Problema: Eseguire codice sincrono bloccante in funzioni asincrone:

@app.get("/slow")
async def slow_endpoint():
    time.sleep(10)  # Blocca l'intero ciclo di eventi!
    return {"status": "finito"}

Soluzione: Utilizza run_in_executor per le operazioni bloccanti:

from fastapi import BackgroundTasks
import asyncio

@app.get("/fast")
async def fast_endpoint():
    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(None, blocking_function)
    return {"result": result}

2. Non utilizzare i modelli di risposta

Problema: Restituire oggetti del database grezzi espone la struttura interna.

Soluzione: Definisci sempre i modelli di risposta:

@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
    return db_user  # Automaticamente filtrato tramite UserResponse

3. Gestione degli errori insufficiente

Problema: Eccezioni non gestite crashano l’applicazione.

Soluzione: Utilizza gestori di eccezioni:

@app.exception_handler(ValueError)
async def value_error_handler(request, exc):
    return JSONResponse(
        status_code=400,
        content={"message": str(exc)}
    )

Risorse dell’ecosistema Python

FastAPI funziona senza problemi con l’ecosistema Python più ampio. Per un’overview completa dei fondamenti di Python, consulta il Python Cheatsheet che copre la sintassi essenziale di Python e i pattern che utilizzerai nelle applicazioni FastAPI.

Conclusione

FastAPI rappresenta un significativo passo avanti nel design dei framework web Python. Adottando funzionalità moderne di Python come gli hint di tipo e async/await, fornisce prestazioni eccezionali e un’esperienza di sviluppo. Che tu stia costruendo un semplice API REST o un’architettura complessa di microservizi, FastAPI fornisce gli strumenti e le prestazioni necessari per le applicazioni di produzione.

La documentazione automatica, la sicurezza dei tipi e il design intuitivo lo rendono un’ottima scelta per sviluppatori principianti e esperti. Mentre l’ecosistema Python continua a evolversi, FastAPI si posiziona come il framework per lo sviluppo moderno di API.

Inizia con un semplice API, esplora la documentazione e adotta gradualmente funzionalità più avanzate man mano che la tua applicazione cresce. La comunità FastAPI è attiva e disponibile, con documentazione e esempi estesi per guidarti.

Risorse esterne e riferimenti