为何调用自定义协程时_run_once未被触发?
Asyncio协程执行疑问解答
我的操作
async def inner() -> None: print("inner") async def main() -> None: print("main start") await inner() print("main end") if __name__ == "__main__": import asyncio asyncio.run(main())
我在asyncio的事件循环中添加了一些print()语句:
def run_forever(self): """Run until stop() is called.""" try: self._thread_id = threading.get_ident() sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook, finalizer=self._asyncgen_finalizer_hook) events._set_running_loop(self) print("start loop in run_forever") # 这里添加的打印 while True: self._run_once() if self._stopping: break def _run_once(self): """Run one full iteration of the event loop. This calls all currently ready callbacks, polls for I/O, schedules the resulting callbacks, and finally schedules 'call_later' callbacks. """ print("_run_once called!") # 这里添加的打印 sched_count = len(self._scheduled) if (sched_count > _MIN_SCHEDULED_TIMER_HANDLES and ...
我的预期结果
- 事件循环调用协程
main() - 协程
inner()被注册到事件循环 - 事件循环在
_run_once()中调用inner()
实际发生的情况
main()被事件循环调用(通过_run_once())main调用inner()inner()执行完成(未与事件循环交互)
日志
start loop in run_forever _run_once called! main start inner main end _run_once called! start loop in run_forever _run_once called! _run_once called! start loop in run_forever _run_once called! _run_once called!
问题
- 为何会出现这种情况?
- 实际上是谁调用了协程
inner()?
解答
问题1:为何会出现这种情况?
因为await inner()是同步调用协程,而非将协程提交给事件循环调度。当main()执行到await inner()时,asyncio会直接在当前调用栈内执行inner()的全部代码——由于inner()内部没有任何异步阻塞操作(比如asyncio.sleep()或IO等待),它会一次性执行完毕,全程不会把控制权交还给事件循环。
只有当协程遇到真正需要挂起等待的异步事件时,才会触发事件循环的调度逻辑。你的预期错误在于默认所有await的协程都会被事件循环单独处理,但实际上纯同步的协程会直接在当前协程的执行流中完成,无需事件循环介入。
问题2:实际上是谁调用了协程inner()?
是main()协程本身直接调用了inner()。执行await inner()时,asyncio的协程调度器会直接运行inner()的字节码,直到它执行结束,随后回到main()继续执行后续代码。整个过程中inner()并未被添加到事件循环的任务队列,因此事件循环没有参与inner()的调用。
内容的提问来源于stack exchange,提问作者Jerry
相关产品推荐
相关产品推荐

