asyncio.run() 不能嵌套调用,因其专为顶层入口设计,会自动创建并关闭事件循环;若当前线程已有运行中的事件循环(如在 async 函数或已启动的 run() 中),再次调用将触发 RuntimeError。

会抛出 RuntimeError: asyncio.run() cannot be called from a running event loop 错误。
为什么不能嵌套调用 asyncio.run()
asyncio.run() 的设计目标是作为程序的**顶层入口**,它会自动创建一个新的事件循环、运行协程、等待完成,然后关闭循环。如果当前线程已经有一个正在运行的事件循环(比如你已经在某个 async 函数里,或已在 asyncio.run() 启动的上下文中),再次调用 asyncio.run() 就会冲突。
常见触发场景:
- 在 async 函数内部直接写
asyncio.run(another_coro()) - 在 Jupyter Notebook 单元格中多次运行
asyncio.run(...)(尤其在未重启内核时) - 在已由 asyncio.run() 启动的协程中,又试图启动另一个独立的 run()
正确替代方案:用 await 代替嵌套 run()
如果你已在异步环境中(比如另一个协程里),应该直接 await 目标协程,而不是用 asyncio.run() 包裹它:
AI 舌诊面诊问诊医疗系统 + 诊疗商城系统源码是一套结合 AI 辅助诊断与商品转化的健康类程序,基于浩创云、ThinkPHP(PHP)开发,支持微信服务号与 H5 端,适合做中医舌诊面诊问答、健康建议推送以及配套诊疗商品的运营。
❌ 错误写法:
asyncio.create_task()
-
asyncio.create_task(coro):立即调度协程,在后台运行,返回 Task 对象 -
await task可等待其完成;不 await 也不影响它运行(但要注意生命周期) - 避免用
asyncio.run()模拟“多线程式”启动——asyncio 是单线程并发,靠事件循环调度
特殊情况:子进程或线程中运行 asyncio.run()
如果你真需要隔离的事件循环(例如在 ThreadPoolExecutor 中执行阻塞 IO 后再跑一段异步逻辑),可以在线程内调用 asyncio.run() —— 因为每个线程默认没有事件循环。但要注意:
- 不能在主线程的 asyncio.run() 内部的线程里再调用 asyncio.run()(除非明确新建线程)
- 这种做法较重,通常应优先考虑用
loop.run_in_executor或重构为纯 await 链路










