你做了faire_toutes_les_requetes_sans_bloquer
an 等待的函数,一个协程,通过使用 async def
.
当您调用可等待函数时,您将创建一个新的协程对象。函数内的代码直到您之后才会运行await在函数上或将其作为任务运行:
>>> 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
a TypeError("Use async with instead")
将引发异常。
这一切都意味着你需要移动loop.run_until_complete()
call out你的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()
asyncio.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 秒内完成。