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

为requests Response扩展自定义方法时触发AttributeError问题求助

如何为requests的Response对象添加自定义校验方法

你遇到的AttributeError: 'Response' object has no attribute 'history',是因为自定义的Response类仅封装了原生requests的Response对象,但未暴露原生对象的属性和方法。requests的Session在处理响应时会访问history等原生Response属性,而你的自定义类未提供这些属性,导致报错。

以下是两种可行的解决方案:

方案1:继承requests原生Response类(推荐)

直接继承requests.Response,自定义类会自动继承原生Response的所有属性和方法,只需添加自定义校验方法即可:

步骤1:定义自定义Response类

import requests

class CustomResponse(requests.Response):
    def validate_ok(self):
        """校验响应状态码为200且返回结果符合要求"""
        assert self.status_code == 200, f"预期状态码200,实际为{self.status_code}"
        json_data = self.json()
        assert 'result' in json_data, "响应JSON中缺少'result'字段"
        assert json_data['status'] == 'ok', f"预期状态为'ok',实际为{json_data['status']}"

    def validate_a(self):
        """自定义校验方法A"""
        # 写入你的校验逻辑
        pass

    def validate_c(self):
        """自定义校验方法C"""
        # 写入你的校验逻辑
        pass

步骤2:重写HTTPAdapter的send方法转换响应

在Adapter中将原生Response转换为自定义Response实例,通过复制属性保留所有原生特性:

class OpenAPIAdapter(requests.adapters.HTTPAdapter):
    def __init__(self, spec):
        super().__init__()
        self.spec = spec

    def send(self, request, **kwargs):
        # 获取原生响应
        response = super().send(request, **kwargs)
        # 创建自定义Response实例并复制原生属性
        custom_resp = CustomResponse()
        custom_resp.__dict__.update(response.__dict__)
        return custom_resp

使用方式

将Adapter挂载到Session后,发起请求即可得到带自定义方法的响应:

session = requests.Session()
session.mount("https://your-api-domain.com", OpenAPIAdapter(your_spec))

resp = session.get("/api/endpoint")
resp.validate_ok()  # 调用自定义校验
resp.validate_a()   # 调用其他自定义校验

方案2:封装原生Response并实现属性代理

如果不想继承原生类,可通过__getattr__方法将所有属性访问代理到封装的原生Response对象:

定义封装类

class Response:
    def __init__(self, response):
        self.response = response

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        # 代理上下文管理器的exit方法
        return self.response.__exit__(exc_type, exc_val, exc_tb)

    def __getattr__(self, name):
        # 访问自定义类未定义的属性时,转发给原生Response
        return getattr(self.response, name)

    def validate_ok(self):
        assert self.response.status_code == 200
        json_data = self.response.json()
        assert 'result' in json_data
        assert json_data['status'] == 'ok'

    def validate_a(self):
        # 自定义校验逻辑
        pass

    def validate_c(self):
        # 自定义校验逻辑
        pass

修改Adapter返回封装类

class OpenAPIAdapter(requests.adapters.HTTPAdapter):
    def __init__(self, spec):
        super().__init__()
        self.spec = spec

    def send(self, request, **kwargs):
        response = super().send(request, **kwargs)
        return Response(response)

原代码报错原因

原自定义Response类仅通过self.response保存原生响应,但未实现属性代理逻辑。当requests的Session尝试访问r.history时,自定义类中无该属性,也未将请求转发给原生对象,因此抛出AttributeError。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:12:55