如何在Python中为requests.Session实现带退避的API请求重试?
最优实现requests Session请求重试(带退避策略)
你的现有循环方案的问题
你的简单循环方案能实现基本重试,但存在几个明显的不足:
- 没有退避策略:连续重试会给API服务器造成额外压力,甚至触发限流机制
- 捕获所有
Exception过于宽泛:像认证失败(401)、参数错误(400)这类根本不该重试的错误也会被重复尝试,纯粹浪费资源 - 无重试日志:出现重试时无法追溯失败原因和重试次数,排查问题很麻烦
推荐方案:用requests的HTTPAdapter结合urllib3.Retry
这是requests官方推荐的重试实现方式,能和Session无缝集成,支持自定义退避策略、重试状态码、重试方法等,灵活性拉满。
完整实现代码
import requests from requests.auth import HTTPBasicAuth from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry def authenticate_api(): session = requests.Session() session.auth = HTTPBasicAuth("", "") session.headers = { "Accept": "application/json", "Content-Type": "application/json", } # 配置重试规则 retry_strategy = Retry( total=3, # 最大重试次数(含首次请求) backoff_factor=1, # 退避因子:重试间隔 = 因子值 * (2 ** (重试次数-1)),比如第1次等1s,第2次2s,第3次4s status_forcelist=[429, 500, 502, 503, 504], # 需要重试的HTTP状态码(限流、服务器故障类) allowed_methods=["GET"] # 允许重试的请求方法,POST/PUT这类有副作用的操作要谨慎开启 ) # 把重试规则挂载到Session的HTTP适配器上 adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("https://", adapter) session.mount("http://", adapter) return session session = authenticate_api() # 发起请求,自动按规则重试 try: response = session.get(URL, timeout=10) response.raise_for_status() except requests.exceptions.RequestException as e: print(f"请求最终失败:{e}")
关键参数说明
total:设定最大重试次数,超过后不再尝试backoff_factor:控制重试间隔的退避逻辑,避免短时间内频繁请求触发限流status_forcelist:精准指定哪些HTTP状态码需要重试,只针对服务器临时故障、限流这类可恢复的错误allowed_methods:限制允许重试的请求方法,POST/PUT这类可能修改数据的请求,盲目重试会导致重复操作,务必谨慎配置
这个方案的优势
- 符合HTTP最佳实践:带退避的重试不会给服务器造成不必要的压力
- 精准控制重试场景:只对应该重试的错误进行操作,避免无效重试
- 与Session深度集成:一次配置后,所有通过该Session发起的请求都会自动应用重试规则,不用在每个请求里写重复循环
- 自带日志支持:开启logging后,urllib3会自动记录重试相关日志,方便排查问题
内容的提问来源于stack exchange,提问作者Aaron
相关产品推荐
相关产品推荐

