python 向聚集数组添加协程

c9qzyr3d  于 2023-10-15  发布在  Python
关注(0)|答案(1)|浏览(115)

我有一个数组的协程中的所有blocking,并在其中一个想添加一个新的数组被收集。我不确定这是否可能...假设pingLoop代码需要添加一个新的例程pingSpecial()并等待它,它也会阻塞,因此它会阻塞pingLoop,这是不好的
循环=[pingLoop()]
await.gather(*loops)

gzjq41n4

gzjq41n41#

我想我明白你的意思了,尽管我用错了“阻止”这个词。协程不应该阻塞,否则没有其他协程有机会在其间运行。所以它们将被顺序执行,你不会从异步编程中受益。
asyncio.gather()是一个有用的特性,当你想在多个协程上await时(当然应该是非阻塞的)。但它也有一些缺点。其中之一就是“你不能在列表中添加另一个协程”!
这只是为了证明:

  1. import asyncio
  2. async def newly_added_coro():
  3. print("newly added coro starts")
  4. await asyncio.sleep(5)
  5. print("newly added coro finished")
  6. async def ping_coro(n, add_task=False):
  7. if add_task:
  8. t = asyncio.create_task(newly_added_coro())
  9. for _ in range(3):
  10. print(f"coro {n} is pinging...")
  11. await asyncio.sleep(1)
  12. async def main():
  13. tasks = [ping_coro(1), ping_coro(2), ping_coro(3, add_task=True)]
  14. await asyncio.gather(*tasks)
  15. asyncio.run(main())

运行这个命令,你会发现它不会等待newly_added_coro(你不会看到print("newly added coro finished")打印到输出中。
幸运的是,Asyncio添加了TaskGroup [1],它正好为您提供了这种能力(以及其他有用的好处)。

  1. import asyncio
  2. async def newly_added_coro():
  3. print("newly added coro starts")
  4. await asyncio.sleep(5)
  5. print("newly added coro finished")
  6. async def ping_coro(n, add_task=False, task_group=None):
  7. if add_task:
  8. task_group.create_task(newly_added_coro())
  9. for _ in range(3):
  10. print(f"coro {n} is pinging...")
  11. await asyncio.sleep(1)
  12. async def main():
  13. async with asyncio.TaskGroup() as tg:
  14. tg.create_task(ping_coro(1))
  15. tg.create_task(ping_coro(2))
  16. tg.create_task(ping_coro(3, add_task=True, task_group=tg))
  17. asyncio.run(main())

只要有tg对象的引用,就可以在协程中使用它,并添加另一个任务,然后沿着其他任务一起等待它。
[1]:这是在Python 3.11中添加的

展开查看全部

相关问题