Como Criar APIs Rápidas com FastAPI em Python

O FastAPI é uma das ferramentas mais populares para criar APIs em Python. Ele combina simplicidade, velocidade e recursos modernos que facilitam o desenvolvimento de aplicações web robustas.

Se você já trabalha com Python e quer criar APIs de forma eficiente, este guia completo vai te ensinar tudo que precisa saber sobre FastAPI.

O Que É FastAPI e Por Que Escolhê-lo

FastAPI é um framework web moderno para criar APIs em Python. Foi desenvolvido por Sebastian Ramirez e lançado em 2018. Desde então, ganhou popularidade rapidamente entre desenvolvedores do mundo todo.

O framework se destaca pela sua alta performance. É um dos frameworks Python mais rápidos disponíveis, competindo com frameworks de outras linguagens como Node.js e Go.

Principais Vantagens do FastAPI

O FastAPI oferece várias vantagens que o tornam atrativo:

  • Velocidade excepcional: Baseado no Starlette e Pydantic, oferece performance comparável a frameworks de linguagens compiladas
  • Documentação automática: Gera documentação interativa automaticamente usando OpenAPI e JSON Schema
  • Validação de dados: Valida automaticamente os dados de entrada e saída usando type hints do Python
  • Suporte a async: Funciona nativamente com programação assíncrona
  • Fácil de aprender: Sintaxe intuitiva para quem já conhece Python

Instalação e Configuração Inicial

Para começar com FastAPI, você precisa instalar o framework e suas dependências.

Preparando o Ambiente

Primeiro, crie um ambiente virtual para seu projeto:

Bash
python -m venv fastapi_env
source fastapi_env/bin/activate  # No Windows: fastapi_env\Scripts\activate

Instalando o FastAPI

Instale o FastAPI junto com um servidor ASGI como o Uvicorn:

Bash
pip install fastapi uvicorn

O Uvicorn é um servidor ASGI que executa aplicações FastAPI em produção e desenvolvimento.

Primeira API com FastAPI

Vamos criar nossa primeira API. Crie um arquivo chamado main.py:

Python
from fastapi import FastAPI

# Criar uma instância do FastAPI
app = FastAPI()

# Definir uma rota básica
@app.get("/")
def ler_raiz():
    return {"mensagem": "Olá, mundo!"}

# Rota com parâmetro
@app.get("/usuarios/{usuario_id}")
def ler_usuario(usuario_id: int):
    return {"usuario_id": usuario_id, "nome": f"Usuario {usuario_id}"}

Para executar a aplicação:

Bash
uvicorn main:app --reload

Acesse http://127.0.0.1:8000 no seu navegador. Você verá:

JSON
{"mensagem": "Olá, mundo!"}

Criando Rotas e Endpoints

As rotas são os caminhos que definem como sua API responde a diferentes requisições. No FastAPI, você define rotas usando decoradores.

Métodos HTTP Principais

O FastAPI suporta todos os métodos HTTP principais:

Python
from fastapi import FastAPI

app = FastAPI()

@app.get("/items")  # Para buscar dados
def listar_items():
    return {"items": ["item1", "item2", "item3"]}

@app.post("/items")  # Para criar novos dados
def criar_item(nome: str):
    return {"item_criado": nome}

@app.put("/items/{item_id}")  # Para atualizar dados
def atualizar_item(item_id: int, nome: str):
    return {"item_id": item_id, "novo_nome": nome}

@app.delete("/items/{item_id}")  # Para deletar dados
def deletar_item(item_id: int):
    return {"item_deletado": item_id}

Parâmetros de Caminho e Query

Você pode capturar parâmetros diretamente da URL:

Python
@app.get("/produtos/{produto_id}")
def obter_produto(produto_id: int, mostrar_detalhes: bool = False):
    produto = {"id": produto_id, "nome": f"Produto {produto_id}"}
    
    if mostrar_detalhes:
        produto["preco"] = 99.90
        produto["categoria"] = "eletrônicos"
    
    return produto

Exemplo de uso: GET /produtos/123?mostrar_detalhes=true

Resultado:

JSON
{
  "id": 123,
  "nome": "Produto 123",
  "preco": 99.90,
  "categoria": "eletrônicos"
}

Validação de Dados com Pydantic

O Pydantic é uma biblioteca que o FastAPI usa para validação de dados. Ele garante que os dados recebidos estejam no formato correto.

Criando Modelos de Dados

Defina modelos usando classes que herdam de BaseModel:

Python
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class Usuario(BaseModel):
    nome: str
    email: str
    idade: int
    ativo: bool = True

class UsuarioResposta(BaseModel):
    id: int
    nome: str
    email: str

@app.post("/usuarios", response_model=UsuarioResposta)
def criar_usuario(usuario: Usuario):
    # Simular criação de usuário
    novo_usuario = {
        "id": 1,
        "nome": usuario.nome,
        "email": usuario.email
    }
    return novo_usuario

Validação Automática

O FastAPI valida automaticamente os dados de entrada:

Python
from pydantic import BaseModel, EmailStr, Field

class Produto(BaseModel):
    nome: str = Field(..., min_length=1, max_length=100)
    preco: float = Field(..., gt=0, description="Preço deve ser maior que zero")
    categoria: str
    em_estoque: bool = True

@app.post("/produtos")
def criar_produto(produto: Produto):
    print(f"Produto criado: {produto.nome}")
    return {"status": "criado", "produto": produto}

Se você enviar dados inválidos, o FastAPI retornará automaticamente uma mensagem de erro detalhada.

Documentação Automática

Uma das funcionalidades mais impressionantes do FastAPI é a geração automática de documentação.

Swagger UI

Acesse http://127.0.0.1:8000/docs para ver a documentação interativa do Swagger UI. Esta interface permite:

  • Visualizar todas as rotas disponíveis
  • Testar endpoints diretamente no navegador
  • Ver exemplos de requisições e respostas
  • Baixar especificações da API

ReDoc

Alternativamente, acesse http://127.0.0.1:8000/redoc para ver a mesma documentação em formato ReDoc, que oferece uma apresentação mais limpa e organizada.

Personalizando a Documentação

Você pode adicionar descrições e metadados para melhorar a documentação:

Python
from fastapi import FastAPI

app = FastAPI(
    title="Minha API de Produtos",
    description="Uma API simples para gerenciar produtos",
    version="1.0.0"
)

@app.post("/produtos", 
          summary="Criar novo produto",
          description="Cria um novo produto no sistema com nome, preço e categoria")
def criar_produto(produto: Produto):
    return {"status": "criado", "produto": produto}

Tratamento de Erros e Status Codes

O tratamento de erros é fundamental para criar APIs robustas. O FastAPI oferece várias formas de lidar com erros.

Códigos de Status HTTP

Use códigos de status apropriados para diferentes situações:

Python
from fastapi import FastAPI, HTTPException, status

app = FastAPI()

produtos_db = {
    1: {"nome": "Notebook", "preco": 2500.00},
    2: {"nome": "Mouse", "preco": 50.00}
}

@app.get("/produtos/{produto_id}")
def obter_produto(produto_id: int):
    if produto_id not in produtos_db:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Produto não encontrado"
        )
    
    return produtos_db[produto_id]

@app.delete("/produtos/{produto_id}")
def deletar_produto(produto_id: int):
    if produto_id not in produtos_db:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Produto não encontrado"
        )
    
    del produtos_db[produto_id]
    return {"mensagem": "Produto deletado com sucesso"}

Manipuladores de Exceção Personalizados

Crie manipuladores customizados para diferentes tipos de erro:

Python
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

class ProdutoNaoEncontradoError(Exception):
    def __init__(self, produto_id: int):
        self.produto_id = produto_id

@app.exception_handler(ProdutoNaoEncontradoError)
async def produto_nao_encontrado_handler(request: Request, exc: ProdutoNaoEncontradoError):
    return JSONResponse(
        status_code=404,
        content={"erro": f"Produto {exc.produto_id} não foi encontrado"}
    )

@app.get("/produtos/{produto_id}")
def obter_produto(produto_id: int):
    if produto_id not in produtos_db:
        raise ProdutoNaoEncontradoError(produto_id)
    
    return produtos_db[produto_id]

Middlewares e CORS

Middlewares são componentes que processam requisições antes que cheguem aos seus endpoints. São úteis para logging, autenticação, e outras funcionalidades transversais.

Configurando CORS

CORS (Cross-Origin Resource Sharing) permite que sua API seja acessada de diferentes domínios:

Python
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# Configurar CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "http://127.0.0.1:3000"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
)

@app.get("/dados")
def obter_dados():
    return {"dados": "Estes dados podem ser acessados via CORS"}

Middleware Personalizado

Crie middlewares personalizados para necessidades específicas:

Python
import time
from fastapi import FastAPI, Request

app = FastAPI()

@app.middleware("http")
async def medir_tempo_requisicao(request: Request, call_next):
    inicio = time.time()
    response = await call_next(request)
    tempo_processamento = time.time() - inicio
    
    response.headers["X-Tempo-Processamento"] = str(tempo_processamento)
    print(f"Requisição processada em {tempo_processamento:.4f} segundos")
    
    return response

Testes Automatizados

Testes são essenciais para garantir que sua API funcione corretamente. O FastAPI facilita a criação de testes automatizados.

Configurando Testes

Instale as dependências de teste:

Bash
pip install pytest httpx

Crie um arquivo test_main.py:

Python
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_ler_raiz():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"mensagem": "Olá, mundo!"}

def test_criar_produto():
    produto_teste = {
        "nome": "Produto Teste",
        "preco": 99.99,
        "categoria": "teste",
        "em_estoque": True
    }
    
    response = client.post("/produtos", json=produto_teste)
    assert response.status_code == 200
    
    dados = response.json()
    assert dados["status"] == "criado"
    assert dados["produto"]["nome"] == "Produto Teste"

def test_produto_nao_encontrado():
    response = client.get("/produtos/999")
    assert response.status_code == 404
    assert "não encontrado" in response.json()["detail"]

Executando Testes

Execute os testes com:

Bash
pytest test_main.py -v

Resultado esperado:

Bash
test_main.py::test_ler_raiz PASSED
test_main.py::test_criar_produto PASSED  
test_main.py::test_produto_nao_encontrado PASSED

Integração com Banco de Dados

Para aplicações reais, você precisará integrar sua API com um banco de dados. Vamos ver como fazer isso com SQLAlchemy.

Instalando Dependências

Bash
pip install sqlalchemy databases asyncpg

Configurando o Banco de Dados

Crie um arquivo database.py:

Python
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, Float, Boolean
from databases import Database

DATABASE_URL = "sqlite:///./produtos.db"

database = Database(DATABASE_URL)
metadata = MetaData()

produtos_table = Table(
    "produtos",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("nome", String(100)),
    Column("preco", Float),
    Column("categoria", String(50)),
    Column("em_estoque", Boolean, default=True)
)

engine = create_engine(DATABASE_URL)
metadata.create_all(engine)

Integrando com FastAPI

Python
from fastapi import FastAPI
from database import database, produtos_table
from pydantic import BaseModel

app = FastAPI()

class Produto(BaseModel):
    nome: str
    preco: float
    categoria: str
    em_estoque: bool = True

class ProdutoResposta(BaseModel):
    id: int
    nome: str
    preco: float
    categoria: str
    em_estoque: bool

@app.on_event("startup")
async def startup():
    await database.connect()

@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()

@app.post("/produtos", response_model=ProdutoResposta)
async def criar_produto(produto: Produto):
    query = produtos_table.insert().values(
        nome=produto.nome,
        preco=produto.preco,
        categoria=produto.categoria,
        em_estoque=produto.em_estoque
    )
    ultimo_id = await database.execute(query)
    
    return {**produto.dict(), "id": ultimo_id}

@app.get("/produtos", response_model=list[ProdutoResposta])
async def listar_produtos():
    query = produtos_table.select()
    resultados = await database.fetch_all(query)
    
    return [dict(resultado) for resultado in resultados]

Deploy e Produção

Quando sua API estiver pronta, você precisa colocá-la em produção. Existem várias opções para fazer deploy de APIs FastAPI.

Preparando para Produção

Crie um arquivo requirements.txt com todas as dependências:

Bash
pip freeze > requirements.txt

Configure variáveis de ambiente em um arquivo .env:

Bash
DATABASE_URL=postgresql://user:password@localhost/produtosdb
SECRET_KEY=sua-chave-secreta-muito-segura
DEBUG=False

Deploy com Docker

Crie um Dockerfile:

Bash
FROM python:3.11-slim

WORKDIR /app

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

COPY . .

EXPOSE 8000

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

Configurações de Produção

Para produção, use configurações otimizadas:

Python
import os
from fastapi import FastAPI

# Configurações baseadas em variáveis de ambiente
DEBUG = os.getenv("DEBUG", "False").lower() == "true"
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./app.db")

app = FastAPI(
    title="API de Produtos",
    debug=DEBUG,
    docs_url="/docs" if DEBUG else None,  # Desabilitar docs em produção
    redoc_url="/redoc" if DEBUG else None
)

Execute com Gunicorn para melhor performance:

Bash
pip install gunicorn
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000

Exemplo Prático Completo

Vamos criar uma API completa para gerenciar uma biblioteca de livros:

Python
from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, Field
from typing import List, Optional
import uuid

app = FastAPI(title="API Biblioteca", version="1.0.0")

# Modelos de dados
class LivroBase(BaseModel):
    titulo: str = Field(..., min_length=1, max_length=200)
    autor: str = Field(..., min_length=1, max_length=100)
    ano_publicacao: int = Field(..., ge=1000, le=2024)
    genero: str = Field(..., min_length=1, max_length=50)
    disponivel: bool = True

class Livro(LivroBase):
    id: str = Field(default_factory=lambda: str(uuid.uuid4()))

class LivroAtualizar(BaseModel):
    titulo: Optional[str] = None
    autor: Optional[str] = None
    ano_publicacao: Optional[int] = None
    genero: Optional[str] = None
    disponivel: Optional[bool] = None

# Banco de dados em memória (para demonstração)
livros_db: List[Livro] = []

# Endpoints
@app.get("/", tags=["Raiz"])
def ler_raiz():
    return {"mensagem": "API da Biblioteca - Gerencie seus livros!"}

@app.post("/livros", response_model=Livro, status_code=status.HTTP_201_CREATED, tags=["Livros"])
def criar_livro(livro: LivroBase):
    novo_livro = Livro(**livro.dict())
    livros_db.append(novo_livro)
    print(f"Livro criado: {novo_livro.titulo}")
    return novo_livro

@app.get("/livros", response_model=List[Livro], tags=["Livros"])
def listar_livros(disponivel: Optional[bool] = None, genero: Optional[str] = None):
    livros_filtrados = livros_db
    
    if disponivel is not None:
        livros_filtrados = [l for l in livros_filtrados if l.disponivel == disponivel]
    
    if genero:
        livros_filtrados = [l for l in livros_filtrados if l.genero.lower() == genero.lower()]
    
    return livros_filtrados

@app.get("/livros/{livro_id}", response_model=Livro, tags=["Livros"])
def obter_livro(livro_id: str):
    for livro in livros_db:
        if livro.id == livro_id:
            return livro
    
    raise HTTPException(
        status_code=status.HTTP_404_NOT_FOUND,
        detail="Livro não encontrado"
    )

@app.put("/livros/{livro_id}", response_model=Livro, tags=["Livros"])
def atualizar_livro(livro_id: str, dados_atualizacao: LivroAtualizar):
    for i, livro in enumerate(livros_db):
        if livro.id == livro_id:
            dados_atualizados = dados_atualizacao.dict(exclude_unset=True)
            livro_atualizado = livro.copy(update=dados_atualizados)
            livros_db[i] = livro_atualizado
            print(f"Livro atualizado: {livro_atualizado.titulo}")
            return livro_atualizado
    
    raise HTTPException(
        status_code=status.HTTP_404_NOT_FOUND,
        detail="Livro não encontrado"
    )

@app.delete("/livros/{livro_id}", tags=["Livros"])
def deletar_livro(livro_id: str):
    for i, livro in enumerate(livros_db):
        if livro.id == livro_id:
            livro_removido = livros_db.pop(i)
            print(f"Livro removido: {livro_removido.titulo}")
            return {"mensagem": "Livro removido com sucesso"}
    
    raise HTTPException(
        status_code=status.HTTP_404_NOT_FOUND,
        detail="Livro não encontrado"
    )

# Endpoint de estatísticas
@app.get("/estatisticas", tags=["Estatísticas"])
def obter_estatisticas():
    total_livros = len(livros_db)
    livros_disponiveis = len([l for l in livros_db if l.disponivel])
    
    generos = {}
    for livro in livros_db:
        generos[livro.genero] = generos.get(livro.genero, 0) + 1
    
    return {
        "total_livros": total_livros,
        "livros_disponiveis": livros_disponiveis,
        "livros_emprestados": total_livros - livros_disponiveis,
        "distribuicao_generos": generos
    }

Esta API completa permite:

  • Criar, listar, obter, atualizar e deletar livros
  • Filtrar livros por disponibilidade e gênero
  • Ver estatísticas da biblioteca
  • Validação automática de dados
  • Documentação interativa automática

Perguntas Frequentes (FAQ)

1. O que é FastAPI?

FastAPI é um framework moderno para criar APIs em Python com alta performance e validação automática de dados.

2. Como posso começar com FastAPI?

Instale com pip install fastapi uvicorn e crie um arquivo Python com suas rotas usando decoradores como @app.get().

3. FastAPI é mais rápido que Flask?

Sim, FastAPI é significativamente mais rápido que Flask, especialmente para operações assíncronas e validação de dados.

4. Preciso conhecer programação assíncrona para usar FastAPI?

Não é obrigatório. FastAPI funciona com funções síncronas normais, mas oferece suporte completo para async/await quando necessário.

5. Como o FastAPI gera documentação automática?

Usa os type hints do Python e modelos Pydantic para gerar automaticamente documentação OpenAPI, disponível em /docs e /redoc.

6. Posso usar FastAPI com bancos de dados?

Sim, FastAPI funciona com qualquer ORM ou biblioteca de banco de dados, incluindo SQLAlchemy, Tortoise ORM e MongoDB.

7. FastAPI é adequado para produção?

Absolutamente. É usado em produção por empresas como Netflix, Uber e Microsoft. Oferece alta performance e recursos empresariais.

8. Como implementar autenticação no FastAPI?

FastAPI oferece suporte nativo para JWT, OAuth2, cookies e outros métodos de autenticação através de dependências.

Compartilhe:

Artigos recentes

Conteúdo do artigo

    Comece a Aprender Python Hoje!

    © Academify 2020-2025. Todos os direitos reservados.

    Conheça o Nosso Curso

    de

    logo do Python
    logo do Python

    Completo!

    Aprenda Python de forma prática e comece a criar seus próprios projetos desde as primeiras aulas. Um curso completo, do básico ao avançado