RuntimeError: Event loop is closed
ID: python/event-loop-closed-runtimeerror
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 3.8+ | active | — | — | — |
| 3.10+ | active | — | — | — |
| 3.12 | active | — | — | — |
Root Cause
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.
generic中文
在创建它的 asyncio 事件循环已关闭后,仍复用了协程或 aiohttp 会话。常见于多次调用 asyncio.run(),或在循环外创建 ClientSession 却在另一次 asyncio.run() 内使用。底层 transport/socket 绑定在已失效的循环上。
Workarounds
-
95% success
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% success
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()
Dead Ends
Common approaches that don't work:
-
90% fail
Silencing the exception leaves the coroutine unfinished and leaks resources; the next call fails differently or hangs.
-
95% fail
A closed loop cannot be restarted; run_until_complete raises RuntimeError immediately.
-
85% fail
Policy changes do not resurrect a closed loop; the error is lifecycle, not platform.