如何在Python Requests重试前捕获首次请求失败并执行额外操作?
实现requests重试前的自定义操作
这个需求很常见,你说得没错——默认的urllib3 Retry机制只会在所有重试次数耗尽后才抛出异常,没法在每次重试前触发自定义逻辑。不过我们可以通过自定义Retry子类来解决这个问题,因为urllib3的Retry类提供了可重写的increment方法,这个方法会在每次准备重试前被调用,正好是我们插入操作的时机。
具体实现步骤
- 继承urllib3的
Retry类,重写increment方法,在调用父类逻辑前执行你的额外操作; - 在
requests_retry_session函数中使用这个自定义的Retry类; - 调整原有代码的异常捕获逻辑(现在每次重试前都会触发操作,最终失败才会进入except块)。
修改后的完整代码
import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import time def do_something_more(): # 执行告知用户API失败即将重试的操作 print("I am doing something more... API请求失败,即将开始重试") # 自定义Retry类,重写increment方法 class CustomRetry(Retry): def increment(self, method=None, url=None, response=None, error=None, _pool=None, _stacktrace=None): # 在重试前执行自定义操作 do_something_more() # 调用父类的increment方法,继续原有的重试逻辑 return super().increment(method, url, response, error, _pool, _stacktrace) def requests_retry_session( retries=3, backoff_factor=0.3, status_forcelist=(500, 502, 504), session=None, ): session = session or requests.Session() # 使用自定义的CustomRetry替代默认Retry retry = CustomRetry( total=retries, read=retries, connect=retries, backoff_factor=backoff_factor, status_forcelist=status_forcelist, ) adapter = HTTPAdapter(max_retries=retry) session.mount('http://', adapter) session.mount('https://', adapter) return session # 使用示例 t0 = time.time() try: response = requests_retry_session().get( 'http://localhost:9999', ) except Exception as x: print('最终请求失败 :(', x.__class__.__name__) else: print('请求最终成功', response.status_code) finally: t1 = time.time() print('总耗时', t1 - t0, 'seconds')
关键说明
CustomRetry类重写的increment方法是urllib3重试逻辑的核心钩子,每次需要重试时都会被调用;- 如果你只想在首次失败后执行一次操作(而不是每次重试前都执行),可以在自定义Retry类里加个计数器,比如:
class CustomRetry(Retry): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.retry_count = 0 def increment(self, method=None, url=None, response=None, error=None, _pool=None, _stacktrace=None): if self.retry_count == 0: do_something_more() self.retry_count += 1 return super().increment(method, url, response, error, _pool, _stacktrace) - 原代码里的
do_somthing_more有拼写错误,已经修正为do_something_more。
内容的提问来源于stack exchange,提问作者rsnhah
相关产品推荐
相关产品推荐

