应初始化计数器为0,循环条件设为retry_count
while 循环怎么配合重试次数控制
直接用
while实现带次数限制的重试,核心是维护一个计数器并主动 break。别依赖while True加无限循环再靠break退出——容易漏写退出条件或误判成功状态。常见错误:把连接成功判断写在循环体末尾,导致最后一次失败后仍自增计数器,多试一次;或者计数器初始化错位(比如从 1 开始但最大允许 3 次,实际只跑 2 轮)。
- 计数器从
0开始,循环条件设为retry_count- 每次尝试前先自增:
retry_count += 1,再执行连接逻辑- 连接成功就用
break跳出,避免多余循环- 失败时可加
time.sleep()避免高频刷请求(尤其对 HTTP 接口)如何判断网络连接是否真正“失败”而非暂时超时
单纯捕获
ConnectionError或TimeoutError不够——有些库(如requests)会把 DNS 解析失败、SSL 握手失败、空响应等都归到不同异常类型下。不区分就重试,可能反复撞在同一类永久性错误上。使用场景:调用第三方 API 时,
401 Unauthorized或404 Not Found是业务错误,重试没意义;而503 Service Unavailable或超时才该重试。
- 用
requests时,要同时检查response.status_code和异常类型- 捕获
requests.exceptions.Timeout、requests.exceptions.ConnectionError、requests.exceptions.RetryError- 对
status_code做白名单过滤,比如只重试5xx和部分429- 避免把
JSONDecodeError当网络错误重试——那是响应体解析失败,大概率服务端已返回内容为什么不能只靠 requests 自带的 urllib3 Retry
requests.Session()的mount("https://", HTTPAdapter(max_retries=...))看似省事,但它默认不重试POST请求(因非幂等),也不处理4xx中的特定码,更没法插入手动退避策略(比如指数退避)。真要可控,还是得自己写while。性能影响:urllib3 的
Retry在底层做连接池复用,自己写 while 则需确保Session复用,否则每次新建连接开销更大。
- 务必复用同一个
requests.Session()实例,不要在循环里反复创建- 若需指数退避,用
time.sleep(2 ** retry_count + random.uniform(0, 1)),别写死sleep(1)- 注意
max_retries=3在 urllib3 里表示“最多重试 3 次”,即总共发 4 次请求;而手动 while 控制时,“重试 3 次”通常指最多发 3 次,语义要对齐完整可运行的小样例(Python + requests)
import requests import time <p>def fetch_with_retry(url, max_retries=3, timeout=5): session = requests.Session() retry_count = 0 while retry_count = 500 or resp.status_code == 429: pass # 可重试的状态码 else: raise Exception(f"Non-retryable status: {resp.status_code}") except (requests.exceptions.Timeout, requests.exceptions.ConnectionError, requests.exceptions.HTTPError): pass # 进入重试流程 except Exception as e: if "Non-retryable" in str(e): raise e if retry_count </p><p>这个结构把重试逻辑收在一个函数里,关键点在于:异常分类处理、状态码白名单、退避延迟只在非最后一次重试时生效。容易被忽略的是 <code>session</code> 复用和 <code>2 ** retry_count</code> 的起始值——第一次重试延迟是 2 秒,不是 1 秒。</p>











