【问题标题】:Python asyncio gather does not exit after task complete任务完成后Python异步收集不退出
【发布时间】:2021-12-28 00:47:18
【问题描述】:

我有一个协程foo1,我使用asyncio.create_task() 调用另一个协程foo2

正如预期的那样,foo1 完成运行并且不等待任务完成,因为没有等待。

我在末尾添加了asyncio.gather() 以完成所有待处理的任务。

问题是gather在任务完成后没有将控制权释放回主程序。 完成后如何让程序结束并运行print("done")

import asyncio

async def foo3(counter):
    for x in range(2):
        await asyncio.sleep(2)
        print(f"foo3 {counter} {x}")

async def foo2():
    counter = 0
    for x in range(2):
        await asyncio.sleep(0.5)
        asyncio.create_task(foo3(counter))
        counter += 1
        print(f"foo2 {x}")

async def foo1():
    t = asyncio.create_task(foo2())  # If I await t the code exits prior to completion of nested tasks.
    pending = asyncio.all_tasks()
    await asyncio.gather(*pending)   # This line never finishes even after foo2 & foo3 are complete
    

if __name__ == "__main__":
    asyncio.run(foo1())
    print("done")
# Output
foo2 0
foo2 1
foo3 0 0
foo3 1 0
foo3 0 1
foo3 1 1

【问题讨论】:

  • 您在foo2 中创建任务,但从未等待它们? (即asyncio.create_task(foo3(counter))

标签: python python-asyncio


【解决方案1】:
  • 完整答案是here

但问题有时可能是一个无限循环,它等待 asyncio.current_task() 完成,这就是它本身。一些答案提出了一些复杂的解决方法,包括检查 coro 名称或 len(asyncio.all_tasks()),但事实证明,利用 set 操作很简单

  • 简答:必须改一行:

await asyncio.gather(*pending)await asyncio.gather(*pending - {asyncio.current_task()})

import asyncio

async def foo2():
    for x in range(3):
        await asyncio.sleep(0.5)
        print(x)

async def foo1():
    asyncio.create_task(foo2())
    pending = asyncio.all_tasks()
    await asyncio.gather(*pending - {asyncio.current_task()})

if __name__ == "__main__":
    asyncio.run(foo1())
    print("done")
0
1
2
done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-07
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多