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

如何在Python Retry中获取有意义的HTTPError异常?

解决requests重试后抛出RetryError而非HTTPError的问题

异常差异说明

首先明确三个异常的本质区别:

  • urllib3.exceptions.MaxRetryError:urllib3底层重试机制抛出的异常,代表所有重试尝试全部失败,没有达到重试终止的成功条件(比如一直返回500直到重试次数耗尽)。
  • requests.exceptions.RetryError:requests对上述底层异常的包装,把urllib3的异常转换成requests体系内的异常类型。
  • requests.exceptions.HTTPError:当请求成功拿到响应,但状态码属于4xx/5xx范围时,调用response.raise_for_status()触发的异常——此时请求已经完成,只是结果不符合业务预期。

你的场景中,重试机制耗尽次数后直接抛出重试相关异常,而非返回最后一次的500响应再触发HTTPError,原因是默认的重试配置会在失败时终止请求并抛出重试异常,不会返回最后一次的响应。

解决方案

有两种简洁的方式实现你想要的效果:

方案1:修改Retry参数,返回最后一次响应后手动触发HTTPError

通过设置raise_on_status=False,让重试机制在耗尽次数后不抛出RetryError,而是返回最后一次请求得到的响应,之后调用raise_for_status()就能和直接请求一样抛出HTTPError:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = requests.Session()
# 配置重试规则,关键开启raise_on_status=False
retry_config = Retry(
    total=3,  # 总重试次数
    status_forcelist=[500],  # 需要重试的状态码
    allowed_methods=["GET"],  # 允许重试的请求方法
    raise_on_status=False  # 重试耗尽后返回最后一次响应,不抛出RetryError
)
adapter = HTTPAdapter(max_retries=retry_config)
session.mount("http://", adapter)
session.mount("https://", adapter)

# 发送请求,后续触发HTTPError
response = session.get("http://example.com/500")
response.raise_for_status()  # 这里会抛出requests.exceptions.HTTPError

方案2:自定义HTTPAdapter,自动处理RetryError并抛出HTTPError

如果不想在业务代码中手动调用raise_for_status(),可以自定义Adapter,在内部捕获RetryError并提取最后一次响应,触发HTTPError:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

class RetryAwareAdapter(HTTPAdapter):
    def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None):
        try:
            return super().send(request, stream, timeout, verify, cert, proxies)
        except requests.exceptions.RetryError as e:
            # 提取重试失败时的最后一次响应
            if e.response is not None:
                # 直接触发HTTPError,和raise_for_status()行为一致
                e.response.raise_for_status()
            # 如果没有响应(比如连接失败),重新抛出原异常
            raise

session = requests.Session()
retry_config = Retry(
    total=3,
    status_forcelist=[500],
    allowed_methods=["GET"]
)
adapter = RetryAwareAdapter(max_retries=retry_config)
session.mount("http://", adapter)
session.mount("https://", adapter)

# 现在请求失败时会直接抛出HTTPError
response = session.get("http://example.com/500")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:50:23