You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python外部定义事件循环时如何自动关闭aiohttp ClientSession

问题原因分析

asyncio.run() 的执行逻辑是「创建全新事件循环→运行传入的协程→运行结束后彻底关闭并销毁事件循环」,而 atexit 注册的回调是在进程退出前才执行,此时 asyncio.run() 创建的事件循环已经被完全销毁,所以 close 方法中调用 loop.run_until_complete 自然会抛出 Event loop is closed 错误。
另外补充:你的代码中给 ClientSession 传 loop 参数是 aiohttp 2.x 版本的老写法,3.0+ 版本已经不需要手动传 loop,会自动绑定当前运行的事件循环,手动传反而容易出现循环不匹配的问题。

问题1解答:外部创建事件循环时实现ClientSession自动关闭的方案
  • 方案1:使用异步上下文管理器(最推荐,符合异步编程规范)
    异步资源的自动管理标准方案是实现 __aenter__ 和 __aexit__ 方法,用户通过 async with 创建实例,退出上下文时自动触发关闭逻辑,完全不需要依赖 atexit,示例代码:
# module/client.py
import aiohttp

class Client:
    def __init__(self):
        self._session = aiohttp.ClientSession()
    
    async def __aenter__(self):
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        # 退出上下文时自动关闭session
        await self._session.close()
    
    async def foo(self):
        # 业务逻辑
        pass

调用侧写法:

# main.py
import asyncio
import module

async def main():
    async with module.Client() as client:
        await client.foo()
    # 退出async with块时session已经完成自动关闭

asyncio.run(main())
  • 方案2:注册事件循环关闭回调(适配不想修改调用方式的场景)
    如果不想用 async with 语法,可以直接给事件循环注册关闭前的回调,替代 atexit,回调会在事件循环被销毁前执行,不会出现循环已关闭的问题:
# module/client.py
import asyncio
import aiohttp

class Client:
    def __init__(self, loop=None):
        self.loop = loop or asyncio.get_running_loop()
        self._session = aiohttp.ClientSession()
        # 注册循环关闭时的自动清理任务
        self.loop.create_task(self._auto_close())
    
    async def _auto_close(self):
        # 等待循环内置的异步生成器销毁完成后再关session
        await self.loop.shutdown_asyncgens()
        if not self._session.closed:
            await self._session.close()
    
    async def foo(self):
        # 业务逻辑
        pass
问题2解答:异步公共方法内部逻辑未全部await的影响

一定会产生功能异常,常见影响包括:

  • 未await的协程不会被调度执行,对应的业务逻辑直接失效,比如内部发请求的协程未await,请求根本不会发送
  • 资源泄漏:未执行完的请求持有的网络连接不会被释放,session关闭时会抛出未完成任务的警告
  • 异常无法捕获:未await的协程如果抛出异常,不会向上抛到调用层,只会触发事件循环的全局异常回调,容易出现静默报错,排查难度极高
  • 时序混乱:未await的逻辑执行时机完全不可控,可能在后续逻辑执行完、甚至程序退出前才执行,导致数据不一致

内容的提问来源于stack exchange,提问作者duhby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:57:01