如何使用Python backoff库实现连续5次405状态码后的重试控制、长休眠及错误打印?
解决连续5次405状态码后触发长休眠的问题
你的核心问题在于原代码里的giveup函数逻辑——只要单次收到405就直接返回True,导致backoff库立刻终止重试,完全没机会累积到5次连续错误。要实现需求,我们需要跟踪连续405的次数,只有当次数达标时才执行长休眠和提示,同时让backoff继续重试直到触发这个条件。
方案一:利用backoff库的钩子+闭包实现
这个方案保留backoff库的退避策略优势,用闭包来安全跟踪连续错误次数(避免全局变量),配合on_backoff钩子在每次重试前检查状态:
import time import backoff import requests def track_consecutive_405(): # 闭包保存连续405的计数器 consecutive_405 = 0 def backoff_handler(details): nonlocal consecutive_405 # 检查当前异常是否是HTTPError且状态码为405 if isinstance(details['exception'], requests.exceptions.HTTPError): response = details['exception'].response if response and response.status_code == 405: consecutive_405 += 1 print(f"连续第{consecutive_405}次收到405状态码") # 达到5次连续错误时执行长休眠 if consecutive_405 >= 5: print("发生405状态错误") time.sleep(60000) # 重置计数器,继续后续重试 consecutive_405 = 0 else: # 非405的错误,重置计数器 consecutive_405 = 0 else: # 其他请求异常(超时、连接错误等),重置计数器 consecutive_405 = 0 return backoff_handler @backoff.on_exception( backoff.expo, # 可根据需求替换为constant等其他退避策略 requests.exceptions.HTTPError, # 精确捕获raise_for_status抛出的HTTP错误 max_tries=None, # 不限制总重试次数,由我们的计数器逻辑控制 on_backoff=track_consecutive_405() # 绑定自定义的重试钩子 ) def publish(url): r = requests.post(url, timeout=10) r.raise_for_status() publish("https://www.google.se/")
方案二:自定义循环+计数器(无需backoff库)
如果你更偏爱完全可控的逻辑,可以参考你之前的计数器思路,优化后实现需求:
import requests import time from backoff import expo # 可选:复用backoff的退避策略计算 def publish(url): consecutive_405 = 0 while True: try: r = requests.post(url, timeout=10) if r.status_code == 405: consecutive_405 += 1 print(f"连续第{consecutive_405}次收到405状态码") if consecutive_405 >= 5: print("发生405状态错误") time.sleep(60000) consecutive_405 = 0 # 用expo策略计算重试间隔,也可以替换为固定时间 time.sleep(expo()(consecutive_405)) else: r.raise_for_status() # 其他HTTP错误抛出异常 print("请求成功") consecutive_405 = 0 break # 成功后退出循环,可根据需求调整 except requests.exceptions.RequestException as e: print(f"请求异常: {str(e)}") consecutive_405 = 0 # 非405异常重置计数器 time.sleep(5) # 短间隔后重试 publish("https://www.google.se/")
关键逻辑说明
- 放弃原giveup的405判断:原代码中
giveup一碰到405就终止重试,这和你需要累积5次的需求完全冲突,必须移除这个判断。 - 连续错误计数:用闭包(方案一)或局部变量(方案二)跟踪连续405的次数,避免全局变量的副作用。
- 阈值触发动作:当计数达到5时,执行长休眠并打印提示,之后可选择重置计数器继续重试,或根据业务需求终止流程。
内容的提问来源于stack exchange,提问作者PythonNewbie
相关产品推荐
相关产品推荐

