对Python异步生成器的误解
我刚接触 asyncio
,特别是 Python 中的异步生成器。这里有一段我不太理解行为的基本代码。它是关于模拟一个等待的睡眠,来获取从远程数据库中返回的值:
import asyncio
async def async_gen():
for i in range(5):
print(f"entering iteration {i}")
await asyncio.sleep(3)
print(f"ending iteration {i}")
yield i
async def main():
async for value in async_gen():
print(value)
asyncio.run(main())
我期望的是:
- 在每次循环中,
i
会打印entering iteration i
- 然后等待 3 秒后,立刻进入下一次循环
i+1
,并打印entering iteration i+1
换句话说,我希望所有的 entering
打印都是立刻显示的,而在 3 秒后,所有的 ending
打印也是立刻显示的。总的时间应该是 3 秒:
entering iteration 0
entering iteration 1
entering iteration 2
entering iteration 3
entering iteration 4
ending iteration 0
0
ending iteration 1
1
ending iteration 2
2
ending iteration 3
3
ending iteration 4
4
但是,执行的结果是每次 entering iteration i
和 ending iteration i
之间都有 3 秒的间隔,总时间变成了 5*3秒 = 15秒:
entering iteration 0
ending iteration 0
0
entering iteration 1
ending iteration 1
1
entering iteration 2
ending iteration 2
2
entering iteration 3
ending iteration 3
3
entering iteration 4
ending iteration 4
4
我确定我有些地方没有理解透彻。
任何帮助都非常欢迎。
非常感谢
祝好
1 个回答
0
在你的情况中,main() 是唯一的任务。如果你想要并发处理,就需要为每次循环创建一个单独的任务。
比如说:
import asyncio
async def some_func(i: int):
print(f"entering iteration {i}")
await asyncio.sleep(3)
print(f"ending iteration {i}")
async def async_gen():
for i in range(5):
yield i
async def main():
tasks = []
async for value in async_gen():
# launching concurrent task
task = asyncio.create_task(some_func(value))
tasks.append(task)
# wait for all tasks to finish
await asyncio.gather(*tasks)
asyncio.run(main())