Avançado 10 min de leitura 01/09/2026

Async/await em Python: quando e por que usar

Concorrência em Python: como async/await funciona, quando usar e armadilhas comuns

Async/await resolve um problema específico: o que fazer enquanto seu programa espera. Espera por uma resposta HTTP, por um arquivo do disco, por uma consulta ao banco. Sem async, o Python trava e não faz mais nada nesse tempo. Com async, ele pode atender outras requisições enquanto espera.

O problema sem async

import requests
import time

def buscar(url):
    return requests.get(url).json()

inicio = time.time()
r1 = buscar("https://api.github.com/users/torvalds")
r2 = buscar("https://api.github.com/users/gvanrossum")
r3 = buscar("https://api.github.com/users/kennethreitz")
print(f"Tempo: {time.time() - inicio:.1f}s")  # ~3s (sequencial)

Com async: requisições simultâneas

import asyncio
import httpx  # versão async do requests: pip install httpx
import time

async def buscar(cliente, url):
    resposta = await cliente.get(url)
    return resposta.json()

async def main():
    async with httpx.AsyncClient() as cliente:
        tarefas = [
            buscar(cliente, "https://api.github.com/users/torvalds"),
            buscar(cliente, "https://api.github.com/users/gvanrossum"),
            buscar(cliente, "https://api.github.com/users/kennethreitz"),
        ]
        resultados = await asyncio.gather(*tarefas)
        for r in resultados:
            print(r["login"], r["public_repos"])

inicio = time.time()
asyncio.run(main())
print(f"Tempo: {time.time() - inicio:.1f}s")  # ~1s (paralelo)

Como funciona o event loop

O Python não cria threads novas. Existe um único event loop — um gerenciador de tarefas que fica verificando quais corrotinas estão prontas para continuar. Quando uma corrotina chega num await, ela "devolve o controle" para o loop, que executa outra enquanto a primeira espera.

Async não é paralelismo — é concorrência. A CPU ainda executa uma coisa por vez, mas o tempo de espera vira tempo útil.

Armadilhas comuns

1. Misturar sync e async

# ERRADO: bloqueia o event loop
async def processar():
    import time
    time.sleep(5)  # trava tudo durante 5s

# CERTO: usa a versão async
async def processar():
    await asyncio.sleep(5)  # só essa corrotina espera

2. Esquecer o await

async def buscar(url):
    resposta = httpx.AsyncClient().get(url)  # ← faltou await
    # resposta é uma corrotina, não o resultado

3. CPU-bound não se beneficia de async

# Async serve para I/O (rede, disco, banco).
# Para cálculos pesados (ML, processamento de imagem), use multiprocessing.
import multiprocessing
with multiprocessing.Pool() as pool:
    resultados = pool.map(processar_imagem, lista_de_imagens)

Async com FastAPI e banco de dados

from fastapi import FastAPI
import asyncpg  # driver async para PostgreSQL

app = FastAPI()
pool = None

@app.on_event("startup")
async def startup():
    global pool
    pool = await asyncpg.create_pool("postgresql://user:senha@host/banco")

@app.get("/usuarios/{id}")
async def buscar_usuario(id: int):
    async with pool.acquire() as conn:
        usuario = await conn.fetchrow("SELECT * FROM usuarios WHERE id=$1", id)
        return dict(usuario)

Quando usar e quando não usar

  • Use async quando o gargalo é I/O: chamadas HTTP, banco, leitura de arquivo
  • Não use async quando o gargalo é CPU: processamento numérico, machine learning, compressão
  • Em Django: suporte a async existe desde o 3.1 mas o ORM ainda tem limitações — prefira usar em views específicas que fazem chamadas HTTP externas

Próximos passos

Com todos esses conceitos, o último passo é garantir que sua aplicação Django chegue ao ar corretamente — e é o que o checklist de deploy cobre.