如何在asyncio3.7的主协程中添加多个任务?

时间:2018-12-14 11:45:35

标签: python-asyncio

我正在尝试将代码从asyncio3.6更新为asyncio3.7。 过渡的一个哲学元素是,强烈建议您在程序中使用单个入口点,尤其是单个asyncio.run(main())

该程序有效:

import asyncio

async def foo():
    while True:
        await asyncio.sleep(1)
        print("hi")

asyncio.run(foo())

该程序有效:

import asyncio

async def foo():
    while True:
        await asyncio.sleep(1)
        print("hi")

async def main():
    await foo()

asyncio.run(main())

但是在打印任何内容之前,以下程序均无错误退出:

import asyncio

async def foo():
    while True:
        await asyncio.sleep(1)
        print("hi")

async def bar():
    while True:
        await asyncio.sleep(1)
        print("ho")

async def main():
    asyncio.create_task(foo())
    asyncio.create_task(bar())

asyncio.run(main())

asyncio3.7是否规定了最佳实践来让主等待某个错误发生的将来?

我知道在main的底部添加一些await future行会使第三个程序“起作用”,但是我对使用create_task来代替main内部的无限协程仍然不满意。具有单个入口点的全部目的是,您可以在单个点上捕获程序引发的所有未处理的异常。但是,当您具有这样的所谓“悬空”任务时,并不会抑制在循环中set_exception_handler的需要。

1 个答案:

答案 0 :(得分:2)

在这种情况下,您只需要以下内容:

async def main():
    # wait for both `foo()` and `bar()` to finish
    await asyncio.gather(foo(), bar())

您还可以使用asyncio.wait(return_when=asyncio.FIRST_COMPLETED)等到 foo()bar()完成,但这需要格外小心,以便实际检索结果以正确传播异常。

等待明确的未来是更高级的用法,最适合当必须在深度嵌套的回调中做出退出程序的决定时。