Tarefas e Gather
Tarefas encapsulam corrotinas para agendamento concorrente no loop de eventos. asyncio.gather aguarda múltiplos awaitables juntos - a base para I/O paralelo em asyncio.
Receita
import asyncio
async def fetch(n: int) -> int:
await asyncio.sleep(0.1)
return n
async def main() -> None:
tasks = [asyncio.create_task(fetch(i)) for i in range(3)]
print(await asyncio.gather(*tasks))
asyncio.run(main())Quando usar isso:
- Chamadas HTTP/DB concorrentes com resultados independentes
- Tarefas em segundo plano junto com o tratamento de requisições
- Fan-in antes de responder (todos os dados são necessários)
- Falha parcial opcional com
return_exceptions=True - Interligando APIs de callback via
create_task
Exemplo Funcional
import asyncio
async def download(url_id: int) -> dict:
await asyncio.sleep(0.05)
if url_id == 2:
raise ValueError("resposta inválida")
return {"id": url_id, "bytes": 100}
async def all_or_nothing() -> None:
try:
await asyncio.gather(*(download(i) for i in range(4)))
except ValueError as exc:
print("falhou", exc)
async def collect_errors() -> None:
results = await asyncio.gather(
*(download(i) for i in range(4)),
return_exceptions=True,
)
for r in results:
print(type(r).__name__, r)
asyncio.run(all_or_nothing())
asyncio.run(collect_errors())O que isso demonstra:
gatherpadrão falha rapidamente na primeira exceçãoreturn_exceptions=Trueretorna objetos de exceção na lista de resultados- Tarefas começam a executar assim que
create_taskas agenda - A ordem dos resultados do
gathercorresponde à ordem de submissão, não à ordem de conclusão
Mergulho Profundo
Tarefa vs Corrotina
| Corrotina | Tarefa | |
|---|---|---|
| Agendamento | Await para executar | Agendada imediatamente |
| Cancelamento | N/A | task.cancel() |
| Inspeção | Limitada | .done(), .exception() |
gather vs TaskGroup
gather- fan-in conveniente, compatível com versões anterioresTaskGroup(3.11+) - concorrência estruturada, cancela irmãos automaticamente em caso de falha
Armadilhas
- create_task sem referência - a tarefa é coletada pelo garbage collector no meio da execução em casos extremos. Correção: mantenha a referência até que esteja concluída.
- gather sem return_exceptions em APIs de sucesso parcial - uma falha perde todos os resultados. Correção:
return_exceptions=Trueou TaskGroup. - Código bloqueante dentro de tarefas - paralisa todas as tarefas. Correção:
to_thread. - Criação de tarefas ilimitada - um milhão de tarefas esgota a memória. Correção: semáforos, pools de workers, lotes.
- Fire-and-forget sem manipulador de erros -
task.exception()nunca recuperado gera um aviso de log. Correção: callback ou wrapperasyncio.create_taskque registra falhas.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| TaskGroup | Código novo, relação pai/filho estrita | Precisa da ergonomia return_exceptions do gather |
| asyncio.as_completed | Processar resultados assim que estiverem prontos | Precisa da lista completa no final |
| Semaphore + gather | Limitar concorrência | Fan-out pequeno |
FAQs
create_task vs ensure_future?
create_task para corrotinas em um loop em execução; ensure_future é mais amplo (interoperabilidade legada).
O gather executa em paralelo?
Concorrente em um único thread - awaits intercalados, não threads paralelas do sistema operacional.
Como limitar a concorrência?
asyncio.Semaphore(n) em torno do trabalho dentro de cada tarefa.
Cancelar tudo em caso de timeout?
async with asyncio.timeout(5): envolvendo gather ou TaskGroup.
gather vs wait?
wait retorna conjuntos de concluídas/pendentes; gather retorna uma lista de valores/exceções.
Posso usar gather com tipos mistos?
Sim - awaitables incluem tarefas, corrotinas, futures.
Nomeando tarefas?
create_task(coro, name="fetch-user") ajuda nos logs de depuração (3.8+).
Exceção em fire-and-forget?
Adicione task.add_done_callback registrando task.exception().
gather preserva a ordem?
Sim - a ordem da lista de resultados corresponde à ordem dos awaitables de entrada.
gather aninhado?
Funciona, mas achate quando possível; use semáforo no nível externo para clareza.
Relacionado
- Concorrência Estruturada - TaskGroup
- Noções Básicas de Asyncio - introdução a corrotinas
- HTTP Assíncrono com httpx/aiohttp - requisições concorrentes
- Depurando Código Assíncrono - vazamentos de tarefas
Versões do Stack: Esta página foi escrita para Python 3.14.0 (estável 3.14, manutenção 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.