我有一个数组的协程中的所有blocking,并在其中一个想添加一个新的数组被收集。我不确定这是否可能...假设pingLoop代码需要添加一个新的例程pingSpecial()并等待它,它也会阻塞,因此它会阻塞pingLoop,这是不好的循环=[pingLoop()]await.gather(*loops)
gzjq41n41#
我想我明白你的意思了,尽管我用错了“阻止”这个词。协程不应该阻塞,否则没有其他协程有机会在其间运行。所以它们将被顺序执行,你不会从异步编程中受益。asyncio.gather()是一个有用的特性,当你想在多个协程上await时(当然应该是非阻塞的)。但它也有一些缺点。其中之一就是“你不能在列表中添加另一个协程”!这只是为了证明:
asyncio.gather()
await
import asyncioasync def newly_added_coro(): print("newly added coro starts") await asyncio.sleep(5) print("newly added coro finished")async def ping_coro(n, add_task=False): if add_task: t = asyncio.create_task(newly_added_coro()) for _ in range(3): print(f"coro {n} is pinging...") await asyncio.sleep(1)async def main(): tasks = [ping_coro(1), ping_coro(2), ping_coro(3, add_task=True)] await asyncio.gather(*tasks)asyncio.run(main())
import asyncio
async def newly_added_coro():
print("newly added coro starts")
await asyncio.sleep(5)
print("newly added coro finished")
async def ping_coro(n, add_task=False):
if add_task:
t = asyncio.create_task(newly_added_coro())
for _ in range(3):
print(f"coro {n} is pinging...")
await asyncio.sleep(1)
async def main():
tasks = [ping_coro(1), ping_coro(2), ping_coro(3, add_task=True)]
await asyncio.gather(*tasks)
asyncio.run(main())
运行这个命令,你会发现它不会等待newly_added_coro(你不会看到print("newly added coro finished")打印到输出中。幸运的是,Asyncio添加了TaskGroup [1],它正好为您提供了这种能力(以及其他有用的好处)。
newly_added_coro
TaskGroup
import asyncioasync def newly_added_coro(): print("newly added coro starts") await asyncio.sleep(5) print("newly added coro finished")async def ping_coro(n, add_task=False, task_group=None): if add_task: task_group.create_task(newly_added_coro()) for _ in range(3): print(f"coro {n} is pinging...") await asyncio.sleep(1)async def main(): async with asyncio.TaskGroup() as tg: tg.create_task(ping_coro(1)) tg.create_task(ping_coro(2)) tg.create_task(ping_coro(3, add_task=True, task_group=tg))asyncio.run(main())
async def ping_coro(n, add_task=False, task_group=None):
task_group.create_task(newly_added_coro())
async with asyncio.TaskGroup() as tg:
tg.create_task(ping_coro(1))
tg.create_task(ping_coro(2))
tg.create_task(ping_coro(3, add_task=True, task_group=tg))
只要有tg对象的引用,就可以在协程中使用它,并添加另一个任务,然后沿着其他任务一起等待它。[1]:这是在Python 3.11中添加的
tg
1条答案
按热度按时间gzjq41n41#
我想我明白你的意思了,尽管我用错了“阻止”这个词。协程不应该阻塞,否则没有其他协程有机会在其间运行。所以它们将被顺序执行,你不会从异步编程中受益。
asyncio.gather()
是一个有用的特性,当你想在多个协程上await
时(当然应该是非阻塞的)。但它也有一些缺点。其中之一就是“你不能在列表中添加另一个协程”!这只是为了证明:
运行这个命令,你会发现它不会等待
newly_added_coro
(你不会看到print("newly added coro finished")
打印到输出中。幸运的是,Asyncio添加了
TaskGroup
[1],它正好为您提供了这种能力(以及其他有用的好处)。只要有
tg
对象的引用,就可以在协程中使用它,并添加另一个任务,然后沿着其他任务一起等待它。[1]:这是在Python 3.11中添加的