Python 3.14中asyncio/asyncpg出现Event loop closed错误的解决方法
问题分析与解决方案
问题重现
你在Python 3.14中运行以下代码时触发RuntimeError: Event loop is closed错误:
import asyncio import asyncpg def adapted_async(): conn = asyncio.run(asyncpg.connect(database='async_test')) asyncio.run(conn.close()) if __name__ == "__main__": adapted_async()
完整报错堆栈:
RuntimeError: Task <Task pending name='Task-5' coro=<Connection.close() running at /Users/Me/Documents/Dev/async_test/.venv/lib/python3.14/site-packages/asyncpg/connection.py:1513> cb=[_run_until_complete_cb() at /opt/local/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/base_events.py:181]> got Future <Future pending cb=[BaseProtocol._on_waiter_completed()]> attached to a different loop During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Users/xof/Documents/Dev/async_test/x.py", line 10, in <module> adapted_async() ~~~~~~~~~~~~~^^ File "/Users/xof/Documents/Dev/async_test/x.py", line 6, in adapted_async asyncio.run(conn.close()) ~~~~~~~~~~~^^^^^^^^^^^^^^ File "/opt/local/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/runners.py", line 204, in run return runner.run(main) ~~~~~~~~~~^^^^^^ File "/opt/local/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/runners.py", line 127, in run return self._loop.run_until_complete(task) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^ File "/opt/local/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/base_events.py", line 719, in run_until_complete return future.result() ~~~~~~~~~~~~~^^ File "/Users/xof/Documents/Dev/async_test/.venv/lib/python3.14/site-packages/asyncpg/connection.py", line 1513, in close await self._protocol.close(timeout) File "asyncpg/protocol/protocol.pyx", line 640, in close File "/opt/local/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/selector_events.py", line 830, in abort self._force_close(None) ~~~~~~~~~~~~~~~~~^^^^^^ File "/opt/local/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/selector_events.py", line 902, in _force_close self._loop.call_soon(self._call_connection_lost, exc) ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/local/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/base_events.py", line 827, in call_soon self._check_closed() ~~~~~~~~~~~~~~~~~~^^ File "/opt/local/Library/Frameworks/Python.framework/Versions/3.14/lib/python3.14/asyncio/base_events.py", line 550, in _check_closed raise RuntimeError('Event loop is closed')
错误原因
你对asyncio.run()的理解有偏差:虽然每次调用asyncio.run()确实会创建新事件循环,但它在协程运行结束后会自动关闭这个循环。
第一次调用asyncio.run(asyncpg.connect(...))时,创建的数据库连接conn会绑定到这次的事件循环上;当该调用结束,这个循环被关闭。第二次调用asyncio.run(conn.close())会创建新的事件循环,但conn的底层网络协议仍然绑定在已关闭的旧循环上,执行close()时会尝试调用旧循环的方法,最终触发“事件循环已关闭”的错误。
正确实现方式
方案一:单协程包裹所有异步操作(推荐)
将连接创建、业务操作、连接关闭放在同一个协程中,只调用一次asyncio.run():
import asyncio import asyncpg async def main(): # 创建连接 conn = await asyncpg.connect(database='async_test') # 这里可以添加数据库操作逻辑 # 关闭连接 await conn.close() if __name__ == "__main__": asyncio.run(main())
方案二:手动管理事件循环(不推荐,仅作演示)
如果必须拆分操作,需确保所有异步操作都在同一个事件循环中执行:
import asyncio import asyncpg def adapted_async(): # 创建事件循环 loop = asyncio.new_event_loop() try: # 在同一循环中执行连接创建和关闭 conn = loop.run_until_complete(asyncpg.connect(database='async_test')) loop.run_until_complete(conn.close()) finally: # 手动关闭循环 loop.close() if __name__ == "__main__": adapted_async()
内容的提问来源于stack exchange,提问作者Christophe
相关产品推荐
相关产品推荐

