永远运行异步事件循环的Python方式是什么?

lve*_*lla 11 python asynchronous python-3.x python-asyncio

文档来看,启动异步应用程序的推荐方法似乎是使用asyncio.run(),所以我的应用程序如下所示:

async def async_main():
    # Everything here can use asyncio.create_task():
    o = ObjectThatMustBeKeptReferenced()
    create_tasks_and_register_callbacks(o)

    # Wait forever, ugly:
    while True:
        await asyncio.sleep(10000)

asyncio.run(async_main())
Run Code Online (Sandbox Code Playgroud)

最后的无限循环async_main()感觉非常错误。在其他语言中,我会永远调用事件循环。所以我尝试了这个:

def main():
    loop = asyncio.get_event_loop()

    # Everything here can use asyncio.create_task():
    o = ObjectThatMustBeKeptReferenced()
    create_tasks_and_register_callbacks(o)

    # Wait forever, pretty:
    loop.run_forever()

main()
Run Code Online (Sandbox Code Playgroud)

RuntimeError: no running event loop这里的问题是,当我在函数内部调用时asyncio.create_task(),即使事件循环是在线程上创建并注册的,这也会失败并出现各种错误。

什么是Pythonic,一种在asyncio事件循环中永远休眠的方法?

use*_*342 8

您可以简单地将sleep循环更改为从未设置的临时事件:

# wait forever
await asyncio.Event().wait()
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以轻松修改它以将事件存储到变量中并将其作为关闭信号传播。

另一种选择是让创建任务的函数返回它创建的任务,在这种情况下,您可以等待它们,即使(或正是因为)它们永远不会完成:

async def async_main():
    o = ObjectThatMustBeKeptReferenced()
    tasks = create_tasks_and_register_callbacks(o)
    # wait forever, or until a task raises
    await asyncio.gather(*tasks)
Run Code Online (Sandbox Code Playgroud)

asyncio.run(async_main())虽然这并不能清楚地传达永远循环的意图,但它的优点是,如果任何任务引发未处理的异常,它将停止程序(并将异常传播到调用的代码)。

  • 好的!现在看来是如此明显!顺便说一句,我使用了 `await asyncio.Future()` 而不是使用 `Event`,因为它是一个更轻量级的对象。 (3认同)
  • 甚至还有点诗意:等待未来!显然,它永远不会到来...... (2认同)