我对使用requests库在Python3中重复失败请求的最佳实践感到好奇。我有一个简单的API包装器,它向构造的URL发出get请求。如果requests引发了异常,我想在引发异常之前重试请求。
我不确定是否有一些我不知道的标准做法。我所拥有的将重复请求10倍,使每次迭代中请求之间的等待时间加倍。
import time
import requests
from requests.exceptions import RequestException
def get_request(*args, max_retry=10, **kwargs):
""" Gets requests.models.Response object using requests.get.
Retry request if request fails, with number of iteration specified
by max_retry. """
def recurse_get_request(*args, retries=0, wait=0.005, **kwargs):
try:
return requests.get(*args, **kwargs)
except RequestException as exc:
if retries > max_retry:
raise RequestException from exc
print("Request failed: (%s). Retrying after %s seconds ..." % (exc, "%.2f" % wait))
time.sleep(wait)
# double the wait time after every iteration
wait *= 2
retries += 1
return recurse_get_request(*args, retries=retries, wait=wait, **kwargs)
return recurse_get_request(*args, **kwargs)
get_request('https://sfbay.craigs.org') # bad url发布于 2021-03-31 16:56:25
您所拥有的是截断指数退避,它已经相当好了。它被称为“截断”,因为它最终停止了重试,完全放弃了。
维基百科上的链接描述也实现了随机化,我称之为截断随机指数退避。如果只有一个客户端,则不需要随机化,但是如果有多个客户机使用相同的退避计划争夺同一资源,则可能会遇到雷鸣羊群问题。随机化有助于避免这种情况。
package 坚韧帮助您使用一个很好的、不引人注目的装饰器轻松地实现所有这些。下面是我如何使用它的一个例子:
import tenacity
# Retry 10 times, starting with 1 second and doubling the delay every time.
_RETRY_ARGS = {
'wait': tenacity.wait.wait_random_exponential(multiplier=1.0, exp_base=2),
'stop': tenacity.stop.stop_after_attempt(10)
}
@tenacity.retry(**_RETRY_ARGS)
def something_that_might_fail():
...
@tenacity.retry(**_RETRY_ARGS)
def something_else_that_might_fail():
...https://stackoverflow.com/questions/66891901
复制相似问题