如何在asyncio.run中使用yield?不可修改__main__的实现方案
解决方案
原代码里asyncio.run(fun(n))会等待整个异步生成器执行完毕后一次性返回所有结果,导致__main__中的循环要等所有值生成完才开始打印。要实现每生成一个值就立即打印,只需修改main函数,让它逐个获取异步生成器的产出值,而非等待全部完成。
修改后的代码如下:
import asyncio async def fun(n): for i in range(n): await asyncio.sleep(i*.1) yield i def main(n): # 创建新的事件循环 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) agen = fun(n) try: # 逐个迭代异步生成器 while True: # 运行到获取下一个异步生成器的值 val = loop.run_until_complete(agen.__anext__()) yield val except StopAsyncIteration: # 异步生成器结束时捕获终止异常 pass finally: # 关闭事件循环 loop.close() if __name__ == '__main__': n = 5 for x in main(n): print(x)
原理说明
- 手动创建事件循环,避开
asyncio.run一次性跑完整个异步生成器的逻辑 - 通过调用异步生成器的
__anext__()方法,配合loop.run_until_complete()逐个获取产出值,每拿到一个就yield出去,让__main__的循环能立即打印 - 捕获
StopAsyncIteration异常来结束迭代,最后关闭事件循环确保资源清理
内容的提问来源于stack exchange,提问作者Jibin
相关产品推荐
相关产品推荐

