You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何调用自定义协程时_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!

问题

  1. 为何会出现这种情况?
  2. 实际上是谁调用了协程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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:17:32