Python Async: por que ainda não virou mainstream?
(tonybaloney.github.io)Python Async: por que ainda não virou mainstream?
O asyncio do Python é uma ferramenta poderosa que pode reduzir tempos de espera e aumentar drasticamente a eficiência de programas em ambientes com muitas tarefas de I/O (entrada/saída). Ainda assim, apesar das várias vantagens, nem todo desenvolvedor Python o adota ativamente, e há algumas razões fundamentais para isso.
1. Fica tudo mais complexo na cabeça: carga cognitiva
A maior barreira é a complexidade. Código síncrono é intuitivo porque basta acompanhar o fluxo de execução de cima para baixo, como se estivéssemos lendo um livro.
Mas código assíncrono é diferente. É como um cozinheiro que, ao preparar macarrão, deixa a massa cozinhando durante o tempo de espera e, ao mesmo tempo, faz o molho; no tempo que sobra, ainda corta os legumes. No fim, a refeição pode ficar pronta mais rápido, mas, na cabeça do cozinheiro, é preciso acompanhar o tempo todo o estado de várias tarefas: “quanto falta para a massa ficar pronta?”, “o molho vai queimar?”.
Como o fluxo de execução do código fica pulando de um lado para outro, fica difícil entender qual tarefa está rodando agora e qual está esperando. Isso torna o processo de depuração especialmente complicado quando surge um bug, porque rastrear a causa fica muito mais difícil.
2. Um ecossistema fragmentado: compatibilidade de bibliotecas
Outro problema do Python é que o ecossistema de bibliotecas está dividido entre “síncrono” e “assíncrono”. Muitas bibliotecas famosas e convenientes (por exemplo, a biblioteca padrão de requisições HTTP requests e muitos ORMs) funcionam apenas de forma síncrona.
Se uma biblioteca síncrona for usada incorretamente dentro de código assíncrono, durante a execução desse código síncrono a principal vantagem da programação assíncrona — o event loop — simplesmente para. É como construir várias faixas numa estrada e usar só uma. Para resolver isso, é preciso aprender e adotar bibliotecas separadas com suporte a async (aiohttp, asyncpg etc.), o que deixa a curva de aprendizado ainda mais íngreme.
3. Só bate em um de cada vez: GIL (Global Interpreter Lock)
O GIL (Global Interpreter Lock) é uma das características crônicas do Python: dentro de um único processo, mesmo que existam várias threads, apenas uma pode executar por vez. O asyncio roda em uma única thread, então não entra em conflito direto com o GIL, mas a existência do GIL limita o alcance do async.
O asyncio é otimizado para aproveitar tempos de espera de I/O (aguardar resposta de rede, esperar leitura de arquivo etc.). Mas, se uma tarefa intensiva de CPU com cálculo muito pesado estiver dentro de uma função async, todo o event loop para até esse cálculo terminar. Durante esse tempo, outras tarefas de I/O ficam sem poder fazer nada além de esperar. No fim, para trabalhos que exigem paralelismo real, ainda existe a limitação de precisar recorrer a outras técnicas, como multiprocessing.
4. Esperança para o futuro: Python 3.14 e a remoção do GIL
Mas há uma notícia bastante animadora sobre essas limitações: o movimento pela remoção opcional do GIL, introduzido experimentalmente a partir do Python 3.13 e que deve amadurecer ainda mais na versão 3.14.
Essa mudança, impulsionada pela proposta PEP 703, tem como objetivo permitir que desenvolvedores executem código Python sem o GIL, caso desejem. Se isso se concretizar, o Python poderá ter multithreading de verdade, com várias threads aproveitando vários núcleos de CPU ao mesmo tempo.
Isso pode gerar uma sinergia enorme quando usado junto com asyncio. Tarefas de I/O podem continuar sendo tratadas com eficiência pelo asyncio, enquanto tarefas de CPU mais pesadas podem ser enviadas para threads separadas e processadas em paralelo sem a limitação do GIL. Essa mudança tende a ser um grande ponto de virada para o ecossistema Python e há grande expectativa de que derrube muitas das barreiras que vinham dificultando a adoção da programação async.
Ainda não há comentários.