Melhorando as requisições assíncronas com Python - Parte 3

Este post é uma continuidade dos posts Lendo arquivos CSV em Python e fazendo requisições e do post Fazendo requests concorrentemente (assíncronas) no Python Após fazermos as requests assíncronas no último post obtivemos uma melhoria signifcativa em nosso processamento, conseguindo paralelizar as requests e reduzindo muito o tempo. Porém não estamos fazendo o melhor proveito da API async do Python, percebam que cada função async também é responsável por também imprimir o resultado e o ideal seria retornarmos os resultados para tratar posteriormente. Vamos fazer isso: ...

26 de julho de 2021 · 3 min de leitura · Lucas Polo

Fazendo requests concorrentemente (assíncronas) no Python - Parte 2

Este post é uma continuação direta do post Lendo arquivos CSV em Python e fazendo requisições - Parte 1 Depois de conseguirmos ler o CSV e conseguirmos fazer requisições em lote, podemos agora iniciar uma primeira otimização, realizar as cotações em paralelo. Para isto usaremos a API assíncrona do Python em conjunto com uma nova biblioteca de requests, a HTTPX. A primeira coisa que faremos é alterar a biblioteca Python que utilizamos, adaptar a requisição e nosso programa para começar a trabalhar assíncronamente. As alterações são principalmente na definição das funções e também nas mudanças para as chamadas das funções assíncronas que agora precisam do await antes: ...

12 de julho de 2021 · 3 min de leitura · Lucas Polo

Micro tutorial de como funcionam corrotinas

import asyncio from random import randint import time async def funcao_assincrona_com_possivel_chamada_sincrona(n: int): # A corrotina é uma função educadinha, que quando vai fazer # algo que pode demorar fala assim: # "Cara, isso aqui vai demorar pois é operação de IO, podem ir fazendo outra coisa" # Assin o interpretador é liberado para executar outras instruções. for i in range(10): print(f'Task {n} - {i}') # Neste ponto (await) a corrotina concede o direito de execução # de volta, ai é permitido rodar outras corrotinas # que estiverem aguardando, é aqui que a rotina fala # "Gente, pode continuar ai que vou demorar aqui um pouco" # Aqui poderia ser uma requisição web demorada, # um acesso a bancos de dados e outras coisas, por exemplo. print(f'Liberando task {n} - {i}') await asyncio.sleep(randint(0,3)) print(f'Retomando task {n} - {i}') # Aqui acontece a quebra, existe a chance (1 em 1000) de # ser executado um processo blocante que irá # blocar todos as tarefas que estão rodando concorrentemente # Ela não é tão educada quanto parecia quando entra aqui. sorte = randint(0, 1000) if sorte == 50: print print(f'Task {n} blocou a GIL no passo {i}, que azar') time.sleep(3) # Isso aqui blocante! print(f'Concluindo task {n} - {i}') async def main(): # Irá criar mil tarefinhas que serão disparadas em "paralelo" (na verdade concorrentemente) tasks_assincronas_que_podem_blocar = { asyncio.create_task( funcao_assincrona_com_coisa_assincrona(i) ) for i in range(10000) } # Executa todas elas, aguardando todas serem concluidas await asyncio.wait( tasks_assincronas_que_podem_blocar, return_when=asyncio.ALL_COMPLETED ) if __name__ == "__main__": asyncio.run(main())

29 de março de 2020 · 2 min de leitura · Lucas Polo