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

如何彻底禁用Python requests与urllib3的请求重试?

问题:无法阻止requests/urllib3的请求重试行为

无论我采取何种操作,都无法停止请求重试。我尝试了ScrapeOps文档中介绍的HTTPAdapter方法,也按照urllib3官方文档设置了retries=False,但当模拟目标URL的连接故障时(期望超时后直接失败,不重试),根据耗时判断程序仍重试了3次(总耗时为超时时间的3倍)。

我尝试了以下几种配置方式:

代码示例1(requests + HTTPAdapter)

import requests
import urllib3

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
   
http = requests.Session()
retries = Retry(total=0, status_forcelist=[ 502, 503, 504 ])
adapter = HTTPAdapter(max_retries=retries)
http.mount("http://", adapter)
r = http.get(url, timeout=mytimeout)

代码示例2(urllib3 PoolManager全局禁用重试)

http = urllib3.PoolManager(retries=False)
r = http.request('GET', url, timeout=mytimeout)

代码示例3(urllib3 请求级禁用重试)

http = urllib3.PoolManager()
r = http.request('GET', url, retries=False, timeout=mytimeout)

即便如此,设置2秒超时后最终失败耗时6秒,3秒超时耗时12秒,显然仍存在重试行为。请问我存在哪些误解,或是有更深层的默认配置导致该问题?


解决方案与问题分析

1. 漏禁连接/读取重试,且未适配HTTPS请求

代码示例1中,Retry(total=0)仅禁用了HTTP状态码触发的重试,但urllib3的Retry默认会对连接错误(如DNS失败、连接超时)和读取超时进行重试。必须显式设置connect=0和read=0来完全禁用所有重试类型;另外你只挂载了http://的适配器,若目标URL是https://,会使用带重试逻辑的默认适配器,必须同时挂载https://:

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

http = requests.Session()
# 完全禁用所有类型的重试
retries = Retry(
    total=0,
    connect=0,
    read=0,
    status_forcelist=[502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retries)
http.mount("http://", adapter)
http.mount("https://", adapter)  # 关键:HTTPS请求也应用无重试适配器
r = http.get(url, timeout=mytimeout)

2. urllib3的retries=False未完全覆盖底层重试逻辑

urllib3中retries=False等价于Retry(total=0),但同样没禁用连接/读取重试。旧版本urllib3(<1.26)对retries=False的处理存在歧义,建议显式创建无重试策略:

import urllib3
from urllib3.util.retry import Retry

# 创建完全禁用重试的策略
no_retry = Retry(total=0, connect=0, read=0)
# 全局配置
http = urllib3.PoolManager(retries=no_retry)
r = http.request('GET', url, timeout=mytimeout)

# 或请求级临时配置
http = urllib3.PoolManager()
r = http.request('GET', url, retries=no_retry, timeout=mytimeout)

3. 超时参数的误解导致耗时计算偏差

你设置的timeout=mytimeout如果是单个数值,requests/urllib3会将其同时作为连接超时和读取超时的上限。连接故障时,每个重试周期都会消耗一次连接超时时间,所以3次重试总耗时就是3 * 连接超时,这和你观察到的2秒超时耗时6秒完全匹配——只有完全禁用重试才能让超时后直接失败。

4. 排查全局默认配置是否被修改

部分第三方库或环境可能全局修改urllib3的默认重试参数,可添加以下代码确认:

import urllib3
print(urllib3.Retry.DEFAULT)  # 查看默认重试参数
print(urllib3.Retry.DEFAULT.connect)  # 默认连接重试次数

如果默认connect值大于0,说明必须显式覆盖该配置才能生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:19:54