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

能否为已有的aiohttp ClientSession添加自定义TraceConfig?

问题:给已创建的aiohttp.ClientSession添加追踪功能报错

我想给一个已经创建好的aiohttp.ClientSession添加自定义追踪功能,写了下面的代码但无法正常运行:

from aiohttp import ClientSession, TraceConfig

async def on_request_start_debug(
        session: aiohttp.ClientSession,
        context, params: aiohttp.TraceRequestStartParams):
    logger.debug(f'HTTP {params.method}: {params.url}')


class MyClient:
    def __init__(self, session: ClientSession):
        trace_config = TraceConfig()
        trace_config.on_request_start.append(on_request_start_debug)
        session.trace_configs.append(trace_config)
        
        self._session = session
        # ...其他逻辑

运行时抛出错误:

RuntimeError: Cannot send non-frozen signal.

错误栈信息:

...
    resp = await session.get(url=url, headers=headers, timeout=timeout)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.12/site-packages/aiohttp/client.py", line 500, in _request
    await trace.send_request_start(method, url.update_query(params), headers)
  File ".../python3.12/site-packages/aiohttp/tracing.py", line 356, in send_request_start
    return await self._trace_config.on_request_start.send(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../python3.12/site-packages/aiosignal/__init__.py", line 33, in send
    raise RuntimeError("Cannot send non-frozen signal.")
RuntimeError: Cannot send non-frozen signal.

原因分析

aiohttp的ClientSession初始化完成后,内部的信号系统(比如追踪回调相关的信号)会被冻结,此时不允许修改trace_configs列表。直接给已创建的session追加新的TraceConfig会触发该错误,因为信号已经处于不可修改的状态。


解决方案

方案1:创建ClientSession时就传入TraceConfig

这是最推荐的方式,在session初始化阶段就配置好追踪逻辑:

from aiohttp import ClientSession, TraceConfig

async def on_request_start_debug(
        session: ClientSession,
        context, params: TraceRequestStartParams):
    logger.debug(f'HTTP {params.method}: {params.url}')

# 先创建并配置trace_config
trace_config = TraceConfig()
trace_config.on_request_start.append(on_request_start_debug)
# 创建session时传入trace_configs参数
session = ClientSession(trace_configs=[trace_config])

# 将配置好的session传入MyClient
client = MyClient(session)

方案2:封装请求方法实现追踪(不修改原session)

如果无法控制原session的创建流程,可以在MyClient内部封装请求方法,手动触发追踪逻辑:

class MyClient:
    def __init__(self, session: ClientSession):
        self._session = session

    async def _traced_request(self, method, url, **kwargs):
        # 手动执行请求开始的追踪日志
        logger.debug(f'HTTP {method}: {url}')
        # 调用原session的请求方法
        return await self._session.request(method, url, **kwargs)

    # 封装常用请求方法
    async def get(self, url, **kwargs):
        return await self._traced_request('GET', url, **kwargs)

    async def post(self, url, **kwargs):
        return await self._traced_request('POST', url, **kwargs)

方案3:基于原session配置创建新的带追踪的session

如果必须使用aiohttp官方的追踪机制,且无法修改原session的创建逻辑,可以基于原session的配置创建新session,并添加trace_config:

class MyClient:
    def __init__(self, session: ClientSession):
        # 创建并配置新的trace_config
        trace_config = TraceConfig()
        trace_config.on_request_start.append(on_request_start_debug)
        # 合并原session的trace_configs和新配置
        new_trace_configs = session.trace_configs + [trace_config]
        # 创建新session,复用原session的核心配置
        self._session = ClientSession(
            connector=session.connector,
            timeout=session.timeout,
            trace_configs=new_trace_configs,
            cookie_jar=session.cookie_jar,
            # 按需添加其他需要复用的参数,比如headers、auth等
        )

注意:这种方式会生成新的session实例,需要确保原session的特殊配置(如自定义连接器、cookie容器)被正确复用,避免资源泄漏。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:50:07