`asyncio.run()` 不等待协程完成

Posted

技术标签:

【中文标题】`asyncio.run()` 不等待协程完成【英文标题】:`asyncio.run()` does not wait for coroutine to finish 【发布时间】:2021-03-20 19:33:19 【问题描述】:

我在 Python 3.7.3 中运行此代码

import asyncio

async def fun(time):
    print(f"will wait for time")
    await asyncio.sleep(time)
    print(f"done waiting for time")

async def async_cenas():
    t1 = asyncio.create_task(fun(1))
    print("after 1")
    t2 = asyncio.create_task(fun(2))
    print("after 2")

def main():
    t1 = asyncio.run(async_cenas())
    print("ok main")
    print(t1)

if __name__ == '__main__':
    main()
    print("finished __name__")

得到这个输出:

after 1
after 2
will wait for 1
will wait for 2
ok main
None
finished __name__

我也期待看到:

done waiting for 1
done waiting for 2

即,为什么期望 asyncio.run(X) 会等待协程完成后再继续。

【问题讨论】:

您的问题是什么? run 等待主协程,然后取消所有其他任务,您可以阅读 implementation 感谢源链接,这有助于@NobbyNobbs @larsks run_until_complete 将遇到完全相同的“问题”,即只等待您告诉它等待的内容。事实上,asyncio.runloop.run_until_complete 的一个相当简单的包装器。 【参考方案1】:

如果您想等待由create_task 生成的所有任务完成,那么您需要明确地通过例如await 依次为它们或gather 或@ 等异步设施来完成它987654322@(区别描述here)。否则会在退出主协程时被asyncio.run取消,传递给asyncio.run

例子:

import asyncio

async def fun(time):
    print(f"will wait for time")
    await asyncio.sleep(time)
    print(f"done waiting for time")

async def async_cenas():
    t1 = asyncio.create_task(fun(1))
    print("after 1")
    t2 = asyncio.create_task(fun(2))
    print("after 2")
    await asyncio.wait(t1, t2, return_when=asyncio.ALL_COMPLETED)
    # or just
    # await t1
    # await t2

def main():
    t1 = asyncio.run(async_cenas())
    print("ok main")
    print(t1)

if __name__ == '__main__':
    main()
    print("finished __name__")
after 1
after 2
will wait for 1
will wait for 2
done waiting for 1
done waiting for 2
ok main
None
finished __name__

【讨论】:

从这里的文档中我不清楚docs.python.org/3.7/library/… 我可以让它在 main() 函数中等待吗?或者只是在 async_cenas() 中? await 仅在 async def 函数(协程)内有效 文档并不完美,但在 cmets 中引用的源代码非常简单

以上是关于`asyncio.run()` 不等待协程完成的主要内容,如果未能解决你的问题,请参考以下文章

Python asyncio run_coroutine_threadsafe 从不运行协程?

python-asyncio

多线程配合协程

python asyncio 异步 I/O - 协程(Coroutine)与运行

异步IO(协程,消息循环队列)

netdev lib 协程异常