Guia Definitivo: APIs Web de Alta
Performance com FastAPI (com uv, ruff,
pyright e CI/CD)
Guia de referência para criação, estruturação, testes, depuração e deploy de APIs robustas e
assíncronas utilizando FastAPI, Pydantic v2 e o ecossistema moderno em Python.
1. Estrutura de Projeto Padronizada (src-layout)
Em aplicações FastAPI profissionais, a separação de responsabilidades (Rotas, Schemas,
Modelos de Banco de Dados, Serviços e Dependências) é essencial para garantir a
manutenibilidade.
Plaintext
meu_servico_api/
├── .github/
│ └── workflows/
│ └── [Link]
├── .vscode/
│ └── [Link]
├── docs/
├── src/
│ └── meu_servico/
│ ├── __init__.py
│ ├── [Link] # Ponto de entrada (instância FastAPI)
│ ├── api/
│ │ ├── __init__.py
│ │ ├── [Link] # Concentrador de rotas (APIRouter)
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── [Link] # Injeção de dependências (Injeção de DB, Auth)
│ │ └── endpoints/
│ │ ├── __init__.py
│ │ ├── [Link]
│ │ └── [Link]
│ ├── core/
│ │ ├── __init__.py
│ │ ├── [Link] # Validação de variáveis de ambiente (pydantic-settings)
│ │ └── [Link] # Sessão Assíncrona e Engine do DB
│ ├── models/ # Entidades do Banco de Dados (SQLAlchemy / SQLModel)
│ │ ├── __init__.py
│ │ └── [Link]
│ ├── schemas/ # DTOs / Schemas de Entrada e Saída (Pydantic)
│ │ ├── __init__.py
│ │ └── [Link]
│ └── services/ # Lógica de Negócios pura
│ ├── __init__.py
│ └── item_service.py
├── tests/
│ ├── __init__.py
│ ├── [Link] # Fixtures de teste (AsyncClient, DB em memória)
│ ├── api/
│ └── unit/
├── .[Link]
├── Dockerfile
├── [Link]
├── [Link]
└── [Link]
2. Inicialização do Projeto com uv
O uv gerencia as dependências e o ambiente virtual de forma extremamente rápida.
Bash
# 1. Inicializar o projeto
uv init meu_servico_api --app
cd meu_servico_api
uv venv
# 2. Ativar o ambiente virtual
# Linux/macOS:
source .venv/bin/activate
# Windows:
.venv\Scripts\activate
# 3. Adicionar dependências de produção do FastAPI
uv add fastapi "uvicorn[standard]" pydantic pydantic-settings
# 4. Adicionar ferramentas de qualidade e testes
uv add --dev ruff pyright pytest httpx pytest-asyncio
3. Configuração de Qualidade e Tipagem
([Link])
Configuração unificada no [Link] contendo as regras do Ruff, Pyright e Pytest com
suporte a código assíncrono:
Ini, TOML
[project]
name = "meu-servico-api"
version = "0.1.0"
description = "API RESTful de alta performance com FastAPI"
readme = "[Link]"
requires-python = ">=3.12"
dependencies = [
"fastapi>=0.111.0",
"pydantic>=2.7.0",
"pydantic-settings>=2.2.0",
"uvicorn[standard]>=0.30.0",
]
[[Link]]
line-length = 88
target-version = "py312"
[[Link]]
select = [
"E", # pycodestyle erros
"W", # pycodestyle avisos
"F", # Pyflakes
"I", # isort (ordenação automática de imports)
"B", # flake8-bugbear
"UP", # pyupgrade (sintaxe moderna de Python)
"ASYNC", # flake8-async (boas práticas com async/await)
]
[[Link]]
quote-style = "double"
indent-style = "space"
[[Link]]
include = ["src"]
pythonVersion = "3.12"
typeCheckingMode = "standard"
reportMissingImports = true
[[Link].ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
pythonpath = ["src"]
4. Implementação do Código do FastAPI
4.1. Configuração com Pydantic Settings
(src/meu_servico/core/[Link])
Python
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
PROJECT_NAME: str = "Meu Serviço API"
API_V1_STR: str = "/api/v1"
DEBUG: bool = False
# Carrega automaticamente do arquivo .env caso exista
model_config = SettingsConfigDict(
env_file=".env", env_file_encoding="utf-8", extra="ignore"
)
settings = Settings()
4.2. Schemas / DTOs com Pydantic v2
(src/meu_servico/schemas/[Link])
Python
from pydantic import BaseModel, ConfigDict, Field
class ItemBase(BaseModel):
title: str = Field(..., min_length=1, max_length=100, example="Cadeira Ergonômica")
description: str | None = Field(default=None, example="Cadeira para escritório")
price: float = Field(..., gt=0, example=850.50)
class ItemCreate(ItemBase):
pass
class ItemResponse(ItemBase):
id: int
model_config = ConfigDict(from_attributes=True)
4.3. Endpoint com Injeção de Dependência
(src/meu_servico/api/v1/endpoints/[Link])
Python
from fastapi import APIRouter, HTTPException, status
from meu_servico.[Link] import ItemCreate, ItemResponse
router = APIRouter()
# Banco de dados temporário em memória para demonstração
_db_items: dict[int, dict] = {}
@[Link]("/", response_model=ItemResponse, status_code=status.HTTP_201_CREATED)
async def create_item(item_in: ItemCreate) -> ItemResponse:
item_id = len(_db_items) + 1
new_item = {"id": item_id, **item_in.model_dump()}
_db_items[item_id] = new_item
return ItemResponse(**new_item)
@[Link]("/{item_id}", response_model=ItemResponse)
async def get_item(item_id: int) -> ItemResponse:
if item_id not in _db_items:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Item não encontrado"
)
return ItemResponse(**_db_items[item_id])
4.4. Instância Principal (src/meu_servico/[Link])
Python
from fastapi import FastAPI
from meu_servico.[Link] import items
from meu_servico.[Link] import settings
app = FastAPI(
title=settings.PROJECT_NAME,
openapi_url=f"{settings.API_V1_STR}/[Link]",
)
# Registro dos roteadores
app.include_router([Link], prefix=f"{settings.API_V1_STR}/items", tags=["Items"])
@[Link]("/health", tags=["Health Check"])
async def health_check() -> dict[str, str]:
return {"status": "ok"}
if __name__ == "__main__":
import uvicorn
[Link]("meu_servico.main:app", host="[Link]", port=8000, reload=True)
5. Testes Assíncronos com pytest e httpx
Crie o arquivo de testes assíncronos em tests/api/test_items.py:
Python
from fastapi import status
from httpx import ASGITransport, AsyncClient
import pytest
from meu_servico.main import app
@[Link]
async def test_create_and_read_item() -> None:
transport = ASGITransport(app=app)
async with AsyncClient(
transport=transport, base_url="[Link]
) as client:
# 1. Criar Item
payload = {
"title": "Teclado Mecânico",
"description": "Switch Brown",
"price": 350.00,
}
response = await [Link]("/api/v1/items/", json=payload)
assert response.status_code == status.HTTP_201_CREATED
data = [Link]()
assert data["title"] == payload["title"]
assert "id" in data
item_id = data["id"]
# 2. Ler Item Criado
get_response = await [Link](f"/api/v1/items/{item_id}")
assert get_response.status_code == status.HTTP_200_OK
assert get_response.json()["title"] == payload["title"]
6. Depuração no VS Code (.vscode/[Link])
JSON
{
"version": "0.2.0",
"configurations": [
{
"name": "FastAPI: Servidor Uvicorn",
"type": "debugpy",
"request": "launch",
"module": "uvicorn",
"args": [
"meu_servico.main:app",
"--reload",
"--host",
"[Link]",
"--port",
"8000"
],
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${workspaceFolder}/src"
}
},
{
"name": "FastAPI: Executar Testes Pytest",
"type": "debugpy",
"request": "launch",
"module": "pytest",
"args": ["-v"],
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${workspaceFolder}/src"
}
}
]
}
7. Containerização Multiestágio Otimizada
(Dockerfile)
Produza contêineres Docker leves mantendo o ambiente isolado via uv.
Dockerfile
# Estágio 1: Build das dependências
FROM python:3.12-slim AS builder
COPY --from=[Link]/astral-sh/uv:latest /uv /bin/uv
WORKDIR /app
# Copiar arquivos de manifesto
COPY [Link] [Link] ./
# Instalar apenas dependências de produção sem cache
RUN uv sync --frozen --no-cache --no-dev
# Estágio 2: Imagem final leve
FROM python:3.12-slim
WORKDIR /app
# Copiar ambiente virtual e código do estágio de build
COPY --from=builder /app/.venv /app/.venv
COPY src/ /app/src/
# Configurar variáveis de ambiente
ENV PATH="/app/.venv/bin:$PATH"
ENV PYTHONPATH="/app/src"
EXPOSE 8000
# Executar Uvicorn diretamente via Python
CMD ["uvicorn", "meu_servico.main:app", "--host", "[Link]", "--port", "8000"]
8. Esteira de Integração Contínua (GitHub Actions)
Arquivo .github/workflows/[Link]:
YAML
name: FastAPI CI Pipeline
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test-and-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Instalar uv
uses: astral-sh/setup-uv@v2
with:
enable-cache: true
- name: Configurar Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Sincronizar Dependências
run: uv sync
- name: Verificar Lint e Formatação (Ruff)
run: |
uv run ruff check .
uv run ruff format --check .
- name: Checagem de Tipos Estática (Pyright)
run: uv run pyright
- name: Executar Testes de Integração (Pytest)
run: uv run pytest
9. Check-list Diário para APIs FastAPI
Ao iniciar o desenvolvimento de uma nova funcionalidade na API:
1. Sincronizar ambiente:
Bash
uv sync
2. Executar servidor de desenvolvimento local:
Bash
uv run uvicorn meu_servico.main:app --reload
○ Acesse a documentação Swagger interativa em:
[[Link]
○ Acesse a documentação ReDoc alternativa em:
[[Link]
3. Validar antes de salvar/subir alterações:
Bash
# Formatar e aplicar correções do Linter
uv run ruff check --fix .
uv run ruff format .
# Checar sistema de tipos estático
uv run pyright
# Executar suíte de testes assíncronos
uv run pytest