404 Not Found

404 Not Found


nginx

Introdução ao FastAPI — Por Que É o Framework Web Python de Próxima Geração

Se Flask é um canivete suíço versátil e Django é um SUV totalmente equipado, então FastAPI é um supercarro elétrico—acelera rapidamente, é eficiente e vem com um painel gerado automaticamente.

1. O Que Você Vai Aprender


2. A História Real da Alice

(1) Problema: O framework síncrono não consegue lidar com milhões de requisições

Alice é uma engenheira de backend construindo o PriceTracker—uma API SaaS de rastreamento de preços para uma plataforma de e-commerce—que precisa lidar com consultas em tempo real para milhões de preços de produtos. Ela inicialmente construiu um protótipo usando Flask, mas quando as requisições concorrentes excederam 1.000 QPS, o modelo síncrono WSGI fez com que cada requisição ficasse enfileirada, e a latência P99 disparou para 3.000 ms. Bob (engenheiro frontend) reclamou do carregamento lento da página, e Charlie (DevOps) disse que o custo da escalabilidade horizontal era muito alto.

(2) A Solução FastAPI

O FastAPI é baseado no protocolo assíncrono ASGI e pode lidar com milhares de conexões concorrentes com um único processo. Type hints geram automaticamente a documentação OpenAPI e validam os dados da requisição, então Alice não precisa escrever código de validação ou documentação manualmente.

PYTHON
from fastapi import FastAPI

app = FastAPI()

@app.get("/products/{product_id}")
async def get_product(product_id: int):
    # Type hint valida automaticamente e gera documentação
    return {"product_id": product_id, "name": "Widget"}

(3) Resultado

Após migrar para o FastAPI, o QPS de nó único do PriceTracker aumentou de 500 para mais de 4.000, a latência P99 caiu para 50 ms, a página frontend do Bob carregou 5 vezes mais rápido, e os custos de servidor do Charlie foram reduzidos em 60%.


3. ASGI e WSGI: Assíncrono É o Futuro

(1) Gargalos de Sincronização WSGI

WSGI (Web Server Gateway Interface) é o padrão tradicional para aplicações web Python; cada requisição ocupa uma thread, e a thread bloqueia e aguarda quando ocorre uma operação de I/O (como uma consulta ao banco de dados ou requisição de rede).

100%
flowchart LR
    Client1[Cliente 1] -->|Requisição| WSGI[Servidor WSGI]
    Client2[Cliente 2] -->|Requisição| WSGI
    Client3[Cliente 3] -->|Requisição| WSGI
    WSGI -->|Thread 1| DB1[(Banco de Dados)]
    WSGI -->|Thread 2| DB1
    WSGI -->|Thread 3 - BLOQUEADA| DB1
Dimensão WSGI ASGI
Modelo de Conexão Uma Requisição, Uma Thread Corrotinas Assíncronas, Single-Thread com Múltiplas Conexões
Limite de Concorrência Limitado pelo pool de threads (tipicamente 10-100) Virtualmente ilimitado (corrotinas são leves)
Espera de I/O Bloqueia a Thread Não bloqueante, alterna para outra corrotina
WebSocket Não suportado Suporte nativo
Servidores Típicos Gunicorn + Flask Uvicorn + FastAPI

(2) As Vantagens Assíncronas do ASGI

ASGI (Asynchronous Server Gateway Interface) é uma extensão assíncrona do WSGI que suporta a sintaxe async/await, permitindo que um único processo lidar com milhares de conexões concorrentes.

PYTHON
import asyncio
import time

# Estilo WSGI - bloqueia a thread
def sync_handler():
    time.sleep(1)  # Thread bloqueada por 1 segundo
    return "done"

# Estilo ASGI - não bloqueante
async def async_handler():
    await asyncio.sleep(1)  # Event loop alterna para outras tarefas
    return "done"

(1) ▶ Exemplo: Comparação de Concorrência Síncrona vs. Assíncrona

PYTHON
import asyncio
import time

async def fetch_price(product_id: int) -> dict:
    # Simular latência de I/O do banco de dados
    await asyncio.sleep(0.1)
    return {"product_id": product_id, "price": 9.99}

async def main():
    start = time.perf_counter()
    # 100 requisições concorrentes - assíncrono termina em ~0.1s
    results = await asyncio.gather(*[fetch_price(i) for i in range(100)])
    elapsed = time.perf_counter() - start
    print(f"Async: {len(results)} itens em {elapsed:.2f}s")

asyncio.run(main())

Saída:

TEXT
Execução Bem-Sucedida

Saída:

TEXT
Async: 100 itens em 0.10s

4. FastAPI vs. Flask vs. Django DRF

(1) Posicionamento no Ecossistema de Frameworks

100%
flowchart LR
    FastAPI[FastAPI] --> Starlette[Starlette ASGI]
    Starlette --> Uvicorn[Servidor Uvicorn]
    Uvicorn --> ASGI_Protocol[Protocolo ASGI]
    FastAPI --> Pydantic[Pydantic V2]
    Flask2[Flask] --> Werkzeug[Werkzeug WSGI]
    Werkzeug --> Gunicorn[Gunicorn]
    Django2[Django DRF] --> Django_Core[Django Core]
Dimensão FastAPI Flask Django DRF
Desempenho (TechEmpower RPS) ~40.000 ~1.200 ~800
Suporte Assíncrono async/await nativo Requer extensão Suporte limitado
Documentação Automática Auto-Geração OpenAPI Requer Flask-RESTX Requer drf-spectacular
Validação de Tipos Validação Automática Pydantic Validação Manual Definição Manual de Serializer
Curva de Aprendizado Baixa (Type hints servem como documentação) Baixa Alta
Escala do Projeto Serviços API de Pequeno a Médio Porte Serviços Pequenos Projetos Full-Stack Grandes

(2) Por Que FastAPI É Mais Adequado para o PriceTracker

Requisitos do PriceTracker Vantagens do FastAPI Desvantagens do Flask
Milhões de consultas por segundo (QPS) Alta concorrência com corrotinas assíncronas Baixa concorrência com bloqueio síncrono
Feeds de preços em tempo real via WebSocket Suporte nativo Não suportado
Documentação Automática da API para Bob Auto-Geração OpenAPI Requer Configuração Adicional
Validação de Dados da Requisição Pydantic Automática Decorador de Validação Personalizado
Autenticação JWT Ferramentas OAuth2 Integradas Requer Bibliotecas de Terceiros

(1) ▶ Exemplo: Comparação de Três Formas de Escrever a Mesma API

PYTHON
# === FastAPI: Type hints = validação automática + documentação ===
from fastapi import FastAPI
from pydantic import BaseModel

class Product(BaseModel):
    name: str
    price: float

app = FastAPI()

@app.post("/products")
async def create_product(product: Product):
    return product  # Auto validado, auto documentado

Saída:

TEXT
# Função definida com sucesso
PYTHON
# === Flask: Validação manual, sem documentação automática ===
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/products", methods=["POST"])
def create_product():
    data = request.get_json()
    if not data or "name" not in data or "price" not in data:
        return jsonify({"error": "Invalid data"}), 400
    if not isinstance(data["price"], (int, float)):
        return jsonify({"error": "Price must be number"}), 400
    return jsonify(data)

5. Type Hints Impulsionam Tudo

(1) O Valor Triplo dos Type Hints

O FastAPI usa type hints do Python para realizar três coisas de uma vez: validação de dados, serialização/desserialização e geração de documentação OpenAPI.

Type Hinting Frameworks Tradicionais FastAPI
Validação de Dados if/else escrito manualmente Pydantic Automático
Serialização JSON json.dumps manual model_dump() Automático
Documentação da API YAML Swagger escrito manualmente Auto-Geração OpenAPI
Auto-Complete do IDE Nenhum Inferência Completa de Tipos

(1) ▶ Exemplo: Validação Automática de Type Hint

PYTHON
from fastapi import FastAPI, Query
from typing import Optional

app = FastAPI()

@app.get("/prices")
async def search_prices(
    min_price: float = Query(0.0, ge=0, description="Preço mínimo em USD"),
    max_price: float = Query(999999.0, le=999999, description="Preço máximo em USD"),
    category: Optional[str] = Query(None, max_length=50),
):
    return {"min_price": min_price, "max_price": max_price, "category": category}

Saída:

TEXT
# Função definida com sucesso

(2) ▶ Exemplo: Documentação OpenAPI Gerada Automaticamente

PYTHON
# Após definir o endpoint acima, visite:
# http://localhost:8000/docs  -> Swagger UI
# http://localhost:8000/redoc -> ReDoc
# http://localhost:8000/openapi.json -> Schema OpenAPI bruto

Saída (trecho de /openapi.json):

TEXT
{
  "paths": {
    "/prices": {
      "get": {
        "summary": "Search Prices",
        "parameters": [
          {"name": "min_price", "in": "query", "schema": {"type": "number", "minimum": 0.0}}
        ]
      }
    }
  }
}

(2) O Papel do Pydantic

Pydantic V2 é um motor de validação de dados para o FastAPI; seu núcleo foi reescrito em Rust, tornando-o 5 a 50 vezes mais rápido que o V1.

Recurso Pydantic V1 Pydantic V2
Motor Central Python Rust (pydantic-core)
Velocidade de Verificação Referência 5-50x Mais Rápido
Validador @validator @field_validator/@model_validator
Configuração class Config model_config = ConfigDict(...)
Serialização .dict() .model_dump()

6. Arquitetura Subjacente: Starlette + Pydantic

(1) Arquitetura de Três Camadas do FastAPI

O FastAPI em si é um wrapper leve; suas capacidades centrais vêm do Starlette (um framework ASGI) e do Pydantic (validação de dados).

Nível Componente Responsabilidades
Camada de Aplicação FastAPI Registro de Rotas, Injeção de Dependência, Geração OpenAPI
Camada ASGI Starlette Middleware, Tratamento de Requisição/Resposta, WebSocket
Camada de Validação Pydantic Validação de dados, serialização e conversão de tipos
Camada de Serviço Uvicorn Servidor ASGI, Gerenciamento do Event Loop

(1) ▶ Exemplo: Usando Recursos do Starlette Diretamente no FastAPI

PYTHON
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse

app = FastAPI()

# Middleware Starlette funciona perfeitamente com FastAPI
app.add_middleware(CORSMiddleware, allow_origins=["*"])

# Classes de resposta Starlette também funcionam
@app.get("/health")
async def health_check():
    return JSONResponse({"status": "healthy"})

Saída:

TEXT
# Função definida com sucesso

(2) ▶ Exemplo: Usando Modelos Pydantic no FastAPI

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field

class PriceCreate(BaseModel):
    product_id: int = Field(gt=0)
    price: float = Field(gt=0, description="Preço em USD")
    currency: str = Field(default="USD", max_length=3)

app = FastAPI()

@app.post("/prices")
async def create_price(data: PriceCreate):
    # dados já validados e parseados pelo Pydantic
    validated = data.model_dump()
    return {"status": "created", "data": validated}

Saída:

TEXT
# Função definida com sucesso

7. Visão Geral do Projeto PriceTracker

(1) O que Alice está tentando construir?

O PriceTracker é uma API SaaS de rastreamento de preços. Suas funcionalidades principais incluem:

Módulo de Funcionalidade Endpoint da API Descrição
Gerenciamento de Produtos /products CRUD Milhões de Registros de Produtos
Rastreamento de Preços /prices CRUD Consultas e Notificações de Preços em Tempo Real
Autenticação de Usuários /auth/login, /auth/register Autenticação JWT de Token Duplo
Planos de Assinatura Free/Pro/Enterprise Permissões Multi-Tenant SaaS
Importação em Lote /import/csv Importação Assíncrona de Arquivos CSV de 1.000 Linhas
Notificações Push em Tempo Real WebSocket /ws/prices Alertas Instantâneos de Mudança de Preço
100%
flowchart LR
    Bob[Bob - Frontend] -->|HTTP/WebSocket| API[PriceTracker API]
    Charlie[Charlie - DevOps] -->|Monitorar| API
    API -->|Consultar| DB[(PostgreSQL)]
    API -->|Cache| Redis[(Redis)]
    API -->|Tarefa| Celery[Celery Worker]
    Celery -->|Scrape| External[Sites Externos]

(1) ▶ Exemplo: PriceTracker—Versão Mínima Funcional

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field
from typing import Optional

app = FastAPI(title="PriceTracker API", version="0.1.0")

class ProductCreate(BaseModel):
    name: str = Field(max_length=200)
    category: str = Field(max_length=100)
    base_price: float = Field(gt=0, description="Preço base em USD")

class ProductResponse(BaseModel):
    id: int
    name: str
    category: str
    base_price: float

PRODUCTS_DB: dict[int, dict] = {}
_counter = 0

@app.post("/products", response_model=ProductResponse)
async def create_product(product: ProductCreate):
    global _counter
    _counter += 1
    record = {"id": _counter, **product.model_dump()}
    PRODUCTS_DB[_counter] = record
    return record

@app.get("/products/{product_id}", response_model=ProductResponse)
async def get_product(product_id: int):
    if product_id not in PRODUCTS_DB:
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="Product not found")
    return PRODUCTS_DB[product_id]

Saída:

TEXT
# Função definida com sucesso

8. Exemplo Abrangente

A força central do FastAPI reside na validação automática e geração de documentação orientada por type hints. O exemplo a seguir demonstra um endpoint completo de consulta de preços que integra parâmetros de caminho, modelos Pydantic e modelos de resposta.

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI(title="PriceTracker Demo")

class PriceResponse(BaseModel):
    product_id: int = Field(gt=0)
    product_name: str
    price: float = Field(gt=0)
    currency: str = "USD"

PRICES_DB: dict[int, dict] = {
    1: {"product_id": 1, "product_name": "Widget", "price": 9.99},
    2: {"product_id": 2, "product_name": "Gadget", "price": 24.50},
}

@app.get("/products/{product_id}", response_model=PriceResponse)
async def get_price(product_id: int):
    if product_id not in PRICES_DB:
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="Product not found")
    return PRICES_DB[product_id]

Saída:

TEXT
GET /products/1 → {"product_id":1,"product_name":"Widget","price":9.99,"currency":"USD"}
GET /products/99 → 404 Not Found

❓ Perguntas Frequentes

P O FastAPI é adequado para projetos de grande escala?
R Sim, é. A injeção de dependência, agrupamento de rotas e sistema de middleware do FastAPI suportam desenvolvimento modular para projetos de grande escala. Empresas como Reddit, Microsoft e Netflix o usam em produção.
P Preciso usar async/await?
R Não, você não precisa. O FastAPI suporta tanto funções de visualização síncronas quanto assíncronas. No entanto, async oferece melhor desempenho em cenários intensivos de I/O (como requisições de banco de dados e rede).
P Qual é a relação entre FastAPI e Starlette?
R O FastAPI é baseado no Starlette, que é um framework ASGI. O FastAPI constrói sobre o Starlette adicionando recursos como validação Pydantic, injeção de dependência e geração automática OpenAPI.
P Preciso usar o Pydantic V2?
R FastAPI 0.100+ usa Pydantic V2 por padrão. V2 tem um núcleo reescrito em Rust e é 5 a 50 vezes mais rápido que V1, então recomendamos usar V2 diretamente.
P O FastAPI pode substituir o Django?
R Depende do caso de uso. O FastAPI é um framework de API que não inclui ORM, interface administrativa ou motor de templates. Se você precisa apenas de serviços API, o FastAPI é a melhor escolha; se precisa de um CMS full-stack, Django é mais adequado.
P Preciso aprender Flask antes de aprender FastAPI?
R Não. A abordagem orientada por type hints do FastAPI é completamente diferente da do Flask, então aprender FastAPI diretamente é mais eficiente e ajuda a evitar concepções prévias baseadas em conceitos similares.

📖 Resumo


📝 Exercícios

  1. Exercício Básico (Dificuldade: ⭐): Instale FastAPI e Uvicorn, crie um endpoint GET que retorna {"message": "Hello PriceTracker"}, e inicie-o usando uvicorn. Dica: pip install fastapi uvicorn
  2. Problema Avançado (Dificuldade ⭐⭐): Adicione o parâmetro de caminho name ao endpoint, retorne {"message": "Hello, {name}"}, e visite /docs no seu navegador para visualizar a documentação gerada automaticamente. Dica: @app.get("/hello/{name}")
  3. Desafio (Dificuldade: ⭐⭐⭐): Crie um modelo Pydantic PriceInput que inclui product_name: str e price: float (deve ser > 0), usa um endpoint POST para receber dados, e retorna o resultado validado. Dica: Herde de BaseModel e use Field(gt=0)

---|

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%