我可以为requests.request设置max_retries吗?
Python的requests模块使用起来简单又优雅,但有一点让我困扰。
有时候会出现一个叫做requests.exception.ConnectionError的错误,错误信息可能是这样的:
Max retries exceeded with url: ...
这意味着requests可能会尝试多次访问数据。但是在文档中根本没有提到过这种可能性。我查看了源代码,也没有找到可以修改默认值(可能是0)的地方。
那么,有没有办法设置requests的最大重试次数呢?
6 个回答
注意哦,Martijn Pieters 的回答不适用于 1.2.1 版本及以上。你不能在全局范围内设置它,除非对库进行修改。
你可以试试这样做:
import requests
from requests.adapters import HTTPAdapter
s = requests.Session()
s.mount('http://www.github.com', HTTPAdapter(max_retries=5))
s.mount('https://www.github.com', HTTPAdapter(max_retries=5))
这段代码不仅会改变 max_retries 的值,还会启用一种叫做“退避策略”的机制。这种机制会让所有 http:// 地址在重试之前先等待一段时间(最多重试5次):
import requests
from requests.adapters import HTTPAdapter, Retry
s = requests.Session()
retries = Retry(total=5,
backoff_factor=0.1,
status_forcelist=[ 500, 502, 503, 504 ])
s.mount('http://', HTTPAdapter(max_retries=retries))
s.get('http://httpstat.us/500')
根据 关于 Retry
的文档:如果 backoff_factor 设置为 0.1,那么在重试之间会等待 [0.05秒, 0.1秒, 0.2秒, 0.4秒, ...]。如果返回的状态码是 500、502、503 或 504,也会强制进行重试。
还有其他一些选项可以让 Retry
更加灵活:
- total – 允许的总重试次数。
- connect – 针对连接相关错误的重试次数。
- read – 针对读取错误的重试次数。
- redirect – 允许的重定向次数。
- method_whitelist – 需要重试的 HTTP 方法的集合(大写)。
- status_forcelist – 需要强制重试的 HTTP 状态码集合。
- backoff_factor – 在尝试之间应用的退避因子。
- raise_on_redirect – 如果重定向次数用完,是否抛出
MaxRetryError
,还是返回一个状态码在 3xx 范围内的响应。 - raise_on_status – 和 raise_on_redirect 类似:如果状态码在 status_forcelist 范围内且重试次数用完,是否抛出异常或返回响应。
注意: raise_on_status 是相对较新的功能,还没有在 urllib3 或 requests 的版本中发布。 raise_on_status 这个参数在 Python 3.6 版本的标准库中出现过。
如果想让请求在特定的 HTTP 状态码上重试,可以使用 status_forcelist。例如,status_forcelist=[503] 会在状态码 503(服务不可用)时重试。
默认情况下,重试只会在以下情况下触发:
- 无法从连接池获取连接。
TimeoutError
- 抛出
HTTPException
(在 Python 3 中来自 http.client,否则来自 httplib)。这通常是一些低级的 HTTP 异常,比如 URL 或协议格式不正确。 SocketError
ProtocolError
注意,这些都是阻止正常 HTTP 响应返回的异常。如果有任何正常的响应产生,就不会进行重试。如果不使用 status_forcelist,即使响应状态是 500 也不会重试。
为了让它在与远程 API 或网页服务器交互时表现得更直观,我会使用上面的代码片段,这样可以在状态为 500、502、503 和 504 时强制重试,这些状态在网络上并不少见,并且在等待足够长的时间后可能会恢复。
实际上,重试的功能是由底层的 urllib3
库来实现的。如果你想设置一个不同的最大重试次数,可以使用 替代的传输适配器。
from requests.adapters import HTTPAdapter
s = requests.Session()
s.mount('http://stackoverflow.com', HTTPAdapter(max_retries=5))
这里的 max_retries
参数可以是一个整数,或者是一个 Retry()
对象;后者可以让你更精细地控制哪些类型的失败会被重试(如果用整数值,它会变成一个只处理连接失败的 Retry()
实例;一旦连接成功后出现的错误默认是不会被处理的,因为这些错误可能会导致其他问题)。
这是一个旧的回答,早于 requests 1.2.1 的发布:
requests
库其实并没有提供很好的配置选项,也不打算这样做(可以参考 这个请求)。在当前版本(requests 1.1)中,重试次数被设置为 0。如果你真的想把它设置为更高的值,就需要全局设置:
import requests
requests.adapters.DEFAULT_RETRIES = 5
这个常量没有文档说明;使用时要小心,因为未来的版本可能会改变处理方式。
更新:这确实发生了变化;在 1.2.1 版本中,添加了设置 max_retries
参数的选项,在 HTTPAdapter()
类中,所以现在你需要使用替代的传输适配器,见上文。猴子补丁的方法不再有效,除非你也补丁 HTTPAdapter.__init__()
的默认值(这非常不推荐)。