Kir*_*sev 156 python python-requests
Python请求模块简单而优雅,但有一点让我感到困惑.可以使用以下消息获取requests.exception.ConnectionError:
Max retries exceeded with url: ...
Run Code Online (Sandbox Code Playgroud)
这意味着请求可以尝试多次访问数据.但是在文档的任何地方都没有提到这种可能性.看一下源代码,我找不到任何可以改变默认值(大概是0)的地方.
那么有可能以某种方式设置请求的最大重试次数吗?
dat*_*man 194
这不仅会更改max_retries,还会启用退避策略,该策略会在重试之前使所有http://地址的请求休眠一段时间(总共5次):
import requests
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
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')
Run Code Online (Sandbox Code Playgroud)
根据Retry的文档:如果backoff_factor为0.1,那么sleep()将在重试之间休眠[0.1s,0.2s,0.4s,...].如果返回的状态代码为500,502,503或504,它也会强制重试.
重试的各种其他选项允许更精细的控制:
注意:raise_on_status是相对较新的,并没有将它变成urllib3或请求的版本.该Retry关键字参数出现在Python版本3.6已经使它成为标准库最多
要使请求在特定HTTP状态代码上重试,请使用status_forcelist.例如,status_forcelist = [503]将在状态码503(服务不可用)上重试.
默认情况下,重试仅针对以下条件触发:
请注意,这些都是阻止接收常规HTTP响应的异常.如果生成任何常规响应,则不会重试.如果不使用status_forcelist,即使状态为500的响应也不会被重试.
为了使其能够以更直观的方式使用远程API或Web服务器,我将使用上面的代码片段,它强制重试状态500,502,503和504,所有这些都不常见于在足够大的退避期间,网络和(可能)可恢复.
Mar*_*ers 144
它是urllib3进行重试的底层库.要设置不同的最大重试计数,请使用备用传输适配器:
from requests.adapters import HTTPAdapter
s = requests.Session()
s.mount('http://stackoverflow.com', HTTPAdapter(max_retries=5))
Run Code Online (Sandbox Code Playgroud)
的max_retries参数采用的整数或一Retry()对象 ; 后者为您提供了对重试类型失败的细粒度控制(整数值转换为Retry()仅处理连接失败的实例;默认情况下不会处理连接后的错误,因为这些可能会导致副作用) .
旧的答案,早于请求的发布1.2.1:
该requests库并没有真正使这个可配置,也没有打算(见这个拉取请求).当前(请求1.1),重试次数设置为0.如果您确实要将其设置为更高的值,则必须全局设置:
import requests
requests.adapters.DEFAULT_RETRIES = 5
Run Code Online (Sandbox Code Playgroud)
这个常数没有记录; 因为未来版本可能会改变处理方式,所以使用它会让您自担风险.
更新:这确实改变了; 在版本1.2.1 中添加了在类上设置max_retries参数的选项,因此现在您必须使用备用传输适配器,请参阅上文.猴子补丁方法不再有效,除非您还修补默认值(非常不推荐).HTTPAdapter()HTTPAdapter.__init__()
小智 58
小心,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))
Run Code Online (Sandbox Code Playgroud)
小智 14
您可以使用 requests 库一次性完成所有工作。如果您收到 429,500,502,503 或 504 状态代码,以下代码将重试 3 次,每次都通过“backoff_factor”设置较长的延迟。请参阅https://findwork.dev/blog/advanced-usage-python-requests-timeouts-retries-hooks/获取不错的教程。
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
method_whitelist=["HEAD", "GET", "OPTIONS"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
http = requests.Session()
http.mount("https://", adapter)
http.mount("http://", adapter)
response = http.get("https://en.wikipedia.org/w/api.php")
Run Code Online (Sandbox Code Playgroud)
Bra*_*och 13
在对这里的一些答案进行了一些努力之后,我找到了一个名为backoff的库,它对我的情况更有效.一个基本的例子:
import backoff
@backoff.on_exception(
backoff.expo,
requests.exceptions.RequestException,
max_tries=5,
giveup=lambda e: e.response is not None and e.response.status_code < 500
)
def publish(self, data):
r = requests.post(url, timeout=10, json=data)
r.raise_for_status()
Run Code Online (Sandbox Code Playgroud)
我仍然建议尽快给出库的本机功能,但如果遇到任何问题或需要更广泛的控制,退避是一种选择.
小智 6
获得更高控制权的一种更简洁的方法可能是将重试内容打包到一个函数中,并使用装饰器使该函数可重试并将异常列入白名单。
我在这里创建了相同的: http //www.praddy.in/retry-decorator-whitelisted-exceptions/
重现该链接中的代码:
def retry(exceptions, delay=0, times=2):
"""
A decorator for retrying a function call with a specified delay in case of a set of exceptions
Parameter List
-------------
:param exceptions: A tuple of all exceptions that need to be caught for retry
e.g. retry(exception_list = (Timeout, Readtimeout))
:param delay: Amount of delay (seconds) needed between successive retries.
:param times: no of times the function should be retried
"""
def outer_wrapper(function):
@functools.wraps(function)
def inner_wrapper(*args, **kwargs):
final_excep = None
for counter in xrange(times):
if counter > 0:
time.sleep(delay)
final_excep = None
try:
value = function(*args, **kwargs)
return value
except (exceptions) as e:
final_excep = e
pass #or log it
if final_excep is not None:
raise final_excep
return inner_wrapper
return outer_wrapper
@retry(exceptions=(TimeoutError, ConnectTimeoutError), delay=0, times=3)
def call_api():
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
100316 次 |
| 最近记录: |