提问人:tobias 提问时间:11/10/2023 更新时间:11/11/2023 访问量:73
如何构建异步发电机?
How to build an asynchronous generator?
问:
当我运行代码时
async def main(*args, **kwargs):
await sub_process1()
async def sub_process1():
iter = await sub_process2()
for i in iter:
yield i
async def sub_process2():
return [1, 2, 3]
我得到
async def main(*args, **kwargs):
> await sub_process1()
E TypeError: object async_generator can't be used in 'await' expression
如果我使用
async def sub_process1():
iter = await sub_process2()
async for i in iter:
yield i
相反。
我该如何解决这个问题?
答:
1赞
Ahmed AEK
11/10/2023
#1
生成器(异步与否)在创建时不做任何工作,当你遍历它(for 循环/异步 for 循环)时,它开始做工作,或者当你调用或调用它时,它开始做等效的工作。next
anext
异步生成器和普通生成器之间的区别在于,异步生成器可以用来挂起自身,这反过来又会挂起异步迭代它的人,虽然不会停止事件循环,但事件循环仍然可以在等待时处理其他异步任务。await
为了遍历异步生成器,您需要使用async for
以下示例说明了差异
import asyncio
import time
async def main(*args, **kwargs):
async for i in sub_process1(): # async generator async for
print(i)
async def sub_process1():
async for i in sub_process2(): # async generator async for
yield i
# what happens under the hood
generator = sub_process2()
try:
while True:
i = await anext(generator)
yield i
except StopAsyncIteration:
pass
async def sub_process2(): # async generator
for i in range(10): # non async generator normal for
yield i
await asyncio.sleep(1) ## suspends sub_process1 and main but not the eventloop
# this could be any awaitable IO, not a sleep
for i in range(10):
yield i
time.sleep(1) ## suspends the eventloop
# this could be any blocking IO, not a sleep
def sub_process3(): # non async generator
for i in range(10):
yield i
# await asyncio.sleep(1) ## won't compile
asyncio.run(main())
评论
await