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

使用aiohttp+ProxyConnector遇Session关闭与未关闭连接器异常

解决aiohttp复用ProxyConnector时的会话关闭与未关闭连接器问题

问题根源

  • 初始报错RuntimeError: Session is closed:默认情况下,ClientSession会成为传入的connector的所有者,当async with块结束关闭会话时,会同时关闭连接器。第二次请求复用已关闭的连接器,就会触发该错误。
  • 添加connector_owner=False后出现的Unclosed connector警告:该参数让会话不再管理连接器的生命周期,但程序结束前没有手动关闭连接器,导致aiohttp抛出资源未释放的警告。

最优解决方案:复用ClientSession

aiohttp的ClientSession设计初衷就是复用,复用会话不仅能避免连接器的生命周期问题,还能利用连接池提升请求效率。修改代码如下:

import asyncio
from typing import Optional

import aiohttp
from aiohttp_socks import ProxyConnector


async def async_get(session: aiohttp.ClientSession, url: str, **kwargs) -> str:
    async with session.get(url=url, **kwargs) as response:
        status_code = response.status
        if status_code <= 201:
            return await response.text()
        raise Exception(f'Unsuccessful request: {status_code}')


async def main():
    proxy = 'socks5://username:password@0.0.0.0:1111'
    connector = ProxyConnector.from_url(url=proxy, rdns=True)
    # 只创建一次会话,循环内复用
    async with aiohttp.ClientSession(connector=connector) as session:
        print(session)
        tasks = [async_get(session, 'https://www.google.com/') for _ in range(3)]
        # 也可以顺序执行:for _ in range(3): await async_get(session, ...)
        await asyncio.gather(*tasks)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

备选方案:手动管理连接器生命周期

如果必须每次创建新的ClientSession,则需要在所有请求完成后手动关闭连接器:

import asyncio
from typing import Optional

import aiohttp
from aiohttp_socks import ProxyConnector


async def async_get(url: str, connector: Optional[ProxyConnector] = None, **kwargs) -> str:
    # 指定connector_owner=False,让会话不关闭连接器
    async with aiohttp.ClientSession(connector=connector, connector_owner=False) as session:
        print(session)
        async with session.get(url=url, **kwargs) as response:
            status_code = response.status
            if status_code <= 201:
                return await response.text()
            raise Exception(f'Unsuccessful request: {status_code}')


async def main():
    proxy = 'socks5://username:password@0.0.0.0:1111'
    connector = ProxyConnector.from_url(url=proxy, rdns=True)
    try:
        for _ in range(3):
            await async_get(url='https://www.google.com/', connector=connector)
    finally:
        # 所有请求完成后手动关闭连接器
        await connector.close()


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

说明

  • 优先选择复用ClientSession的方案,这是aiohttp官方推荐的最佳实践,能有效提升性能并避免资源管理问题。
  • 手动关闭连接器时,务必确保在所有请求完成后执行,否则可能导致正在进行的请求失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:16:26