Вы сделали faire_toutes_les_requetes_sans_bloquer
функцию ожидаемой , сопрограмму, используя async def
.
Когда вы вызываете ожидаемую функцию, вы создаете новый объект сопрограммы.Код внутри функции не будет работать до тех пор, пока вы не дождетесь функции или не запустите ее как задачу:
>>> async def foo():
... print("Running the foo coroutine")
...
>>> foo()
<coroutine object foo at 0x10b186348>
>>> import asyncio
>>> asyncio.run(foo())
Running the foo coroutine
Вы хотите сохранить эту функцию синхронной , потому что вы не запускаете цикл до тех пор, пока внутри этой функции:
def faire_toutes_les_requetes_sans_bloquer():
loop = asyncio.get_event_loop()
# ...
loop.close()
print("Fin de la boucle !")
Однако вы также пытаетесь использовать объект aiophttp.ClientSession()
, а это асинхронный менеджер контекста ожидается, что вы будете использовать его с async with
, а не только с with
, и поэтому должны выполняться в стороне от ожидаемой задачи.Если вы используете with
вместо async with
, будет сгенерировано исключение TypeError("Use async with instead")
.
Все это означает, что вам нужно переместить loop.run_until_complete()
вызов из вашего faire_toutes_les_requetes_sans_bloquer()
функция, так что вы можете оставить это в качестве основной задачи для запуска;Вы можете позвонить и дождаться asycio.gather()
напрямую, затем:
async def faire_toutes_les_requetes_sans_bloquer():
async with aiohttp.ClientSession() as session:
futures = [requete_sans_bloquer(x, session) for x in range(10)]
await asyncio.gather(*futures)
print("Fin de la boucle !")
print("Non bloquant : ")
start = datetime.datetime.now()
loop.run(faire_toutes_les_requetes_sans_bloquer())
exec_time = (datetime.datetime.now() - start).seconds
print(f"Pour faire 10 requêtes, ça prend {exec_time}s\n")
Я использовал новую asyncio.run()
функцию (Python 3.7 и выше) для запуска единственной главной задачи.Это создает выделенный цикл для этой сопрограммы верхнего уровня и запускает ее до завершения.
Далее необходимо переместить закрывающую скобку )
в выражении await resp.json()
:
uid = (await response.json())['uuid']
Вы хотите получить доступ к клавише 'uuid'
по результату await
, а не к сопрограмме, которую создает response.json()
.
С этими изменениями ваш код работает, но версия asyncio завершается за секундувремя;Вы можете распечатать микросекунды:
exec_time = (datetime.datetime.now() - start).total_seconds()
print(f"Pour faire 10 requêtes, ça prend {exec_time:.3f}s\n")
На моем аппарате синхронный код requests
примерно за 4-5 секунд, а код asycio завершится менее чем за 0,5 секунды.