为何协程'hello_world'无法正确执行await操作?
问题原因与解决方案
为什么程序会提前终止?
核心问题出在asyncio.run()的工作机制上:它会运行你传入的主协程,直到该协程完全执行完毕,随后立刻关闭事件循环。你的代码流程里,func_runner这个主协程在调用完not_a_coroutine()之后就没有后续逻辑了,会快速执行完毕,导致asyncio.run()直接关闭事件循环——这时候你通过loop.create_task()创建的hello_world任务甚至还没来得及真正进入休眠阶段(刚打印完"Hello"就被强制取消),自然不会等到一年的休眠结束。
具体拆解你的代码执行顺序:
asyncio.run(func_runner(not_a_coroutine))启动事件循环,开始运行func_runner协程func_runner执行await asyncio.sleep(0),只是短暂让出控制权,很快回到协程继续执行- 调用普通函数
not_a_coroutine(),它获取当前运行的事件循环,创建coro_runner(hello_world)的任务并加入循环 not_a_coroutine()执行完毕,回到func_runner,此时func_runner没有更多代码,协程执行完成asyncio.run()检测到主协程结束,立刻关闭事件循环,所有未完成的任务(包括hello_world)被强制取消,程序直接退出
你看到只打印了"Hello",是因为hello_world刚执行到打印语句,还没进入await asyncio.sleep(...)的休眠,事件循环就被关闭了。
如何修复这个问题?
要解决问题,核心是让asyncio.run()运行的主协程(也就是func_runner)等待你在普通函数里创建的hello_world任务完成。这里提供一种直观的修改方案:
import asyncio from typing import Callable async def hello_world(): print('Hello', end=' ') await asyncio.sleep(31_536_000) # 1 Year print('world.') async def func_runner(func: Callable): await asyncio.sleep(0) # 获取普通函数创建的任务,并等待它完成 task = func() await task async def coro_runner(func: Callable): await func() # 调用hello_world def not_a_coroutine(): loop = asyncio.get_running_loop() task = loop.create_task(coro_runner(hello_world)) # 返回创建的任务,让主协程可以等待它 return task asyncio.run(func_runner(not_a_coroutine))
修改点说明:
- 让
not_a_coroutine()返回创建的任务对象 - 在
func_runner中接收这个任务对象,并通过await task等待它完成 - 这样
func_runner会一直等待hello_world任务执行完毕,asyncio.run()才会关闭事件循环,你的休眠逻辑就能正常工作了
内容的提问来源于stack exchange,提问作者lemi57ssss
相关产品推荐
相关产品推荐

