症状
调用 asyncio.run 的代码崩溃并报 RuntimeError: asyncio.run() cannot be called from a running event loop,或 This event loop is already running。该故障在 notebook、异步 Web 处理器以及自管事件循环的框架中很常见,因为周边环境已在同一线程运行着循环。
诊断
用 grep 找出所有启动循环的位置;在已有循环的环境里改用 await 或创建任务;若同步代码必须调用异步代码,则用 asyncio.to_thread 把工作放到独立线程。
grep -rn "asyncio.run\|run_until_complete\|new_event_loop" .
根因
两个事件循环冲突。asyncio.run 会新建循环,而在同一线程已有循环运行时无法调用,因此嵌套创建循环才是缺陷根源。
修复
异步代码中直接 await 协程;同步代码在顶层只启动一次循环,或把阻塞工作放到独立线程中使用专属循环。坚持自启循环的库应从同步上下文调用或做相应包装。
验证
再次执行该路径确认不再报 RuntimeError,并检查协程的副作用或返回值,确保它确实执行而非被静默跳过。
常见陷阱
用 try/except 吞掉该异常会让协程根本没运行却看似成功;应修正循环结构而非掩盖错误。