Python asyncio: Guia completo para entender o básico e iniciar na programação assíncrona

Python asyncio: Guia completo para entender o básico e iniciar na programação assíncrona





Python asyncio: entendendo o básico



Python asyncio: entendendo o básico

Conceitos fundamentais, fluxo de execução e padrões práticos para escrever código assíncrono de forma limpa e eficiente.

1. O que é asyncio e por que ele importa

Ao lidarmos com tarefas de IO (requisições de rede, leitura/gravação de disco, timers), o desempenho pode ficar limitado pelo tempo ocioso de espera. O asyncio oferece uma forma cooperativa de concorrência sem recorrer a múltiplas threads, utilizando um loop de eventos (event loop) para alternar entre várias corrotinas. Com async/await, podemos estruturar código assíncrono de modo que pareça síncrono, mantendo a organização e a legibilidade.

Pontos-chave:

  • Conceito de corrotina: uma função assíncrona que pode ceder o controle ao loop de eventos.
  • Event loop: gerencia a execução, schedule e conclusão de tarefas.
  • Não bloquear o loop: chamadas bloqueantes precisam ser executadas com cuidado ou offloadadas para executores.

2. Corrotinas, async/await e o loop de eventos

Em Python, uma função marcada com async def retorna uma corrotina. Para executá-la, você precisa de um loop de eventos. O operador await suspende a execução da corrotina atual até o resultado ficar disponível, permitindo que outras tarefas avancem.

  • async def define corrotina; await suspende a execução até o resultado.
  • asyncio.create_task(corrotina()) cria e agenda uma Task para execução concorrente.
  • await asyncio.sleep(x) é uma forma de ceder controle ao loop sem bloquear o restante das tarefas.
  • O loop de eventos pode ser gerenciado explicitamente ou através de asyncio.run, que cria e encerra o loop.

Exemplo conceitual: criar várias corrotinas que aguardam IO simulado sem bloquear umas às outras.

3. Padrões, APIs úteis e práticas recomendadas

Abaixo estão padrões comuns para compor código assíncrono elegante e resiliente.

  • Criação de tarefas: use asyncio.create_task para iniciar operações concorrentes.
  • Agrupar tarefas: asyncio.gather para esperar várias tarefas ao mesmo tempo e coletar resultados.
  • Aguardando com timeout: asyncio.wait_for para impor limites de tempo em operações assíncronas.
  • Cancelamento: é possível cancelar tarefas com task.cancel(), tratando as CancelledError corretamente.
  • Tratamento de exceções: gather pode retornar exceções como parte dos resultados; use return_exceptions quando necessário.
  • Executores para código bloqueante: utilize loop.run_in_executor para isolar operações bloqueantes de CPU ou IO.

4. Exemplo prático: tarefas concorrentes com asyncio

Aqui temos um exemplo simples que demonstra como iniciar várias tarefas que simulam operações de IO e coletar seus resultados ao final.

import asyncio

async def fetch_simulado(nome: str, delay: float) -> str:
    print(f"Tarefa {nome} iniciada (delay={delay}s)")
    await asyncio.sleep(delay)  # simula IO não bloqueante
    print(f"Tarefa {nome} concluída")
    return f"resultado-{nome}"

async def main() -> None:
    tarefas = [
        asyncio.create_task(fetch_simulado("A", 1.0)),
        asyncio.create_task(fetch_simulado("B", 0.75)),
        asyncio.create_task(fetch_simulado("C", 1.25)),
    ]

    # aguarda todas as tarefas e coleta os resultados
    resultados = await asyncio.gather(*tarefas)
    print("Resultados obtidos:", resultados)

if __name__ == "__main__":
    asyncio.run(main())

Notas sobre o exemplo:

  • As tarefas são iniciadas quase simultaneamente e o loop de eventos alterna entre elas conforme vão liberando tempo de CPU, simulando IO não bloqueante.
  • Em cenários reais, substitua asyncio.sleep por chamadas assíncronas de rede ou disco (aiohttp, aioredis, etc.).
  • Para código bloqueante existente, use executores com run_in_executor para evitar bloquear o loop.

Curtiu o conteúdo? Explore mais posts para aprofundar o tema de Python assíncrono e padrões de design em código real.

Python
Asyncio
Desempenho

Leia também:
Introdução ao asyncio
asyncio avançado: padrões e práticas
threading vs asyncio: escolhas de concorrência

Dicas adicionais e exemplos podem ser encontrados navegando pelos posts relacionados.