RuntimeError: 事件循环已关闭
RuntimeError: Event loop is closed
ID: python/event-loop-closed-runtimeerror
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| 3.8+ | active | — | — | — |
| 3.10+ | active | — | — | — |
| 3.12 | active | — | — | — |
根因分析
在创建它的 asyncio 事件循环已关闭后,仍复用了协程或 aiohttp 会话。常见于多次调用 asyncio.run(),或在循环外创建 ClientSession 却在另一次 asyncio.run() 内使用。底层 transport/socket 绑定在已失效的循环上。
English
An asyncio coroutine or aiohttp session is reused after the event loop that created it has been closed. Common when calling asyncio.run() multiple times, or when a ClientSession is created outside the loop and used inside a different asyncio.run() call. The underlying transport/socket is bound to a now-dead loop.
解决方案
-
95% 成功率
async def main(): async with aiohttp.ClientSession() as session: async with session.get(url) as r: return await r.text() asyncio.run(main()) # session lives and dies inside this loop -
85% 成功率
import asyncio loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) try: loop.run_until_complete(main()) finally: loop.run_until_complete(loop.shutdown_asyncgens()) loop.close()
无效尝试
常见但无效的做法:
-
90% 失败
Silencing the exception leaves the coroutine unfinished and leaks resources; the next call fails differently or hangs.
-
95% 失败
A closed loop cannot be restarted; run_until_complete raises RuntimeError immediately.
-
85% 失败
Policy changes do not resurrect a closed loop; the error is lifecycle, not platform.