使用urllib2在超时时重试加载页面?

时间:2014-08-13 04:03:32

标签: python python-2.7

我正在尝试强制Python在我收到超时错误时重试加载页面。有没有办法可以让它重试特定次数,可能是在特定的时间延迟之后?

任何帮助都将不胜感激。

谢谢。

3 个答案:

答案 0 :(得分:3)

urllib2没有内置任何内容,但您可以自己编写。

棘手的部分是,正如urlopen文档所说,无论出现什么问题,你只需要URLError。那么,你怎么知道它是暂停还是其他什么?

好吧,如果您查找URLError,它会说reason对于远程网址是socket.error。如果你查找socket.error,它会告诉你它是IOErrorOSError的子类(取决于你的Python版本)。如果您查找OSError,它会告诉您它有errno表示潜在错误。

那么,你获得超时的errno值?我愿意打赌它是EINPROGRESS,但我们肯定会发现:

>>> urllib.urlopen('http://127.0.0.1', timeout=0)
urllib2.URLError: <urlopen error [Errno 36] Operation now in progress>
>>> errno.errorcode[36]
'EINPROGRESS'

(您可以使用数字36,但不保证在各个平台上都相同; errno.EINPROGRESS应该更便携。)

所以:

import errno
import urllib2

def retrying_urlopen(retries, *args, **kwargs):
    for i in range(retries):
        try:
            return urllib2.urlopen(*args, **kwargs)
        except URLError as e:
            if e.reason.errno == errno.EINPROGRESS:
                continue
            raise

如果你认为这很糟糕而且应该不那么笨重......好吧,我认为每个人都同意。例外情况已经两次彻底改善,另外一个很大的问题,以及沿途的各种小变化。但如果你坚持使用2.7,你就无法从这些改进中获益。

如果无法迁移到Python 3.4,可能会转移到requestsurllib3等第三方模块。这两个库都有Timeout的单独异常类型,而不是让您了解通用URLError的详细信息。

答案 1 :(得分:0)

查看requests库。如果您只想等待指定的时间(不是整个下载,直到您从服务器获得响应),只需将timeout参数添加到标准URL请求中,以秒为单位:

r = requests.get(url, timeout=10)

如果超过timeout时间,则会引发requests.exceptions.Timeout异常,可以按照您的意愿处理。例如,您可以将请求放在try / except块中,如果它被引发则捕获异常,并在完全失败之前再次重试连接指定的次数。

您可能还想查看requests.adapters.HTTPAdapter,其中包含max_retries个参数。它通常在请求Session中使用,并且根据文档,它为请求会话提供了一个通用案例接口,通过实现传输适配器接口来联系HTTP和HTTPS URL。

答案 2 :(得分:0)

即使我是Python的新手,但我认为即使这样一个简单的解决方案也可以解决问题,

首先将东西视为无,其中东西是page_source。还记得我只考虑了URLError异常。您可能希望根据需要添加更多内容。

import urllib2
import time
stuff=None
max_attempts=4
r=0
while stuff is None and r<max_attempts:
    try:
        response = urllib2.urlopen('http://www.google.com/ncr', timeout=10)
        stuff = response.read()
    except urllib2.URLError:
        r=r+1
        print "Re-trying, attempt -- ",r
        time.sleep(5)
        pass
print stuff

希望有所帮助。

此致

马里兰州穆赫辛