能否为已有的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
相关产品推荐
相关产品推荐

