我正在尝试将代码从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
的需要。
答案 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()
完成,但这需要格外小心,以便实际检索结果以正确传播异常。
等待明确的未来是更高级的用法,最适合当必须在深度嵌套的回调中做出退出程序的决定时。