失败时如何重试urllib2.request?

iTa*_*ayb 29 python urllib2 decorator

urllib2.request到达超时,一个urllib2.URLError异常.重试建立连接的pythonic方法是什么?

jte*_*ace 58

我会使用重试装饰器.还有其他的,但这个很好用.以下是如何使用它:

@retry(urllib2.URLError, tries=4, delay=3, backoff=2)
def urlopen_with_retry():
    return urllib2.urlopen("http://example.com")
Run Code Online (Sandbox Code Playgroud)

如果URLError引发,这将重试该功能.检查上面的链接以获取有关参数的文档,但基本上它将重试最多4次,每次指数退避延迟加倍,例如3秒,6秒,12秒.

  • 问题不在于异常,而在于引发异常的代码。如果无法运行代码,如何重试?Python 中没有匿名块的概念。这是可行的,但不直观。 (2认同)

bgr*_*itl 6

有一些专门从事这方面的图书馆.

一个是退避,其设计具有特别功能的敏感性.装饰器通过任意可调用的返回生成器,产生连续的延迟值.最大重试时间为32秒的简单指数退避可以定义为:

@backoff.on_exception(backoff.expo,
                      urllib2.URLError,
                      max_value=32)
def url_open(url):
    return urllib2.urlopen("http://example.com")
Run Code Online (Sandbox Code Playgroud)

另一种是重试,它具有非常相似的功能,但是API通过预定义的关键字args指定重试参数.


Lin*_*nPy 6

对于Python3,您可以使用urllib3.Retry

from urllib3 import Retry, PoolManager


retries = Retry(connect=5, read=2, redirect=5, backoff_factor=0.1)
http = PoolManager(retries=retries)
response = http.request('GET', 'http://example.com/')
Run Code Online (Sandbox Code Playgroud)

如果 backoff_factor 为 0.1,则 :func:.sleep将在重试之间休眠 [0.0s, 0.2s, 0.4s, ...]。它永远不会比 :attr: 长Retry.BACKOFF_MAX。urllib3 将休眠::

        {backoff factor} * (2 ** ({number of total retries} - 1))
Run Code Online (Sandbox Code Playgroud)


jfs*_*jfs 5

要重试超时,您可以按照@Karl Barker 在评论中的建议捕获异常:

assert ntries >= 1
for _ in range(ntries):
    try:
        page = urlopen(request, timeout=timeout)
        break # success
    except URLError as err:
        if not isinstance(err.reason, socket.timeout):
           raise # propagate non-timeout errors
else: # all ntries failed 
    raise err # re-raise the last timeout error
# use page here
Run Code Online (Sandbox Code Playgroud)