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

如何在aiohttp异常场景下获取完整请求数据(无需全局变量)

无需全局变量获取aiohttp完整请求信息的替代方案

已知CustomClientRequest可行,这里提供两种无需全局变量、也不用猴子补丁的实现方式,都能在请求异常时拿到包含自动请求头、带查询参数URL的完整请求数据:

1. 继承ClientRequest扩展请求跟踪

直接继承aiohttp.ClientRequest,在预处理阶段完成后把完整请求信息存在请求实例自身的属性里,后续异常发生时直接从请求对象中读取。

import aiohttp
from aiohttp.client_reqrep import ClientRequest

class TrackedClientRequest(ClientRequest):
    async def _prepare(self, *args, **kwargs):
        # 先执行父类的预处理逻辑,生成最终的URL、请求头等数据
        await super()._prepare(*args, **kwargs)
        # 把完整请求信息存在实例属性里
        self.prepared_info = {
            "url": str(self.url),
            "headers": dict(self.headers),
            "method": self.method,
            "request_data": self.data if hasattr(self, "data") else None
        }

# 使用时给ClientSession指定自定义请求类
async def main():
    async with aiohttp.ClientSession(request_factory=TrackedClientRequest) as session:
        try:
            # 发起一个会失败的请求
            async with session.get("https://example.invalid", headers={"X-Custom-Header": "test"}) as resp:
                await resp.text()
        except Exception as e:
            # 从请求实例中获取预处理后的完整信息
            # 若异常来自请求预处理阶段,可通过异常上下文拿到请求对象
            if hasattr(e.__context__, "request"):
                req = e.__context__.request
                print("异常时的完整请求信息:", req.prepared_info)
            print("异常详情:", str(e))

2. 封装请求方法,绑定信息到异常

不修改ClientRequest类,而是封装session的请求流程:先完成请求预处理,把完整信息附加到后续抛出的异常对象上,异常时直接从异常属性读取。

import aiohttp
from aiohttp.client_reqrep import ClientRequest

async def tracked_request(session, method, url, **kwargs):
    # 创建请求对象并完成预处理
    req = ClientRequest(method, url, session=session, **kwargs)
    await req.prepare(session)
    # 整理完整请求信息
    request_info = {
        "url": str(req.url),
        "headers": dict(req.headers),
        "method": req.method
    }
    try:
        # 执行请求
        return await session._request(req)
    except Exception as e:
        # 把请求信息绑定到异常对象
        setattr(e, "request_info", request_info)
        raise

async def main():
    async with aiohttp.ClientSession() as session:
        try:
            await tracked_request(session, "GET", "https://example.invalid", headers={"X-Custom": "demo"})
        except Exception as e:
            print("异常时的请求信息:", getattr(e, "request_info", "无可用信息"))
            print("异常:", str(e))

关于TraceConfig失败的原因

TraceConfig的on_request_start钩子触发时,请求可能还没完成预处理(比如session级别的自动请求头还未合并到请求中),如果异常发生在预处理阶段,就拿不到完整的最终请求数据。上面两种方案都是在预处理完成后再执行请求,确保拿到的是最终的请求信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 12:23:14