[英]Retry loading page on timeout with urllib2?
我在遇到超时错误时试图强制Python重新尝试加载页面。 有没有一种方法可以让我重试特定的次数(可能在特定的时间延迟之后)?
任何帮助,将不胜感激。
谢谢。
urllib2
没有内置任何功能,但是您可以自己编写。
棘手的是,如urlopen
文档所说,无论出什么问题,您都只会收到URLError
。 那么,您怎么知道是超时还是其他?
好吧,如果您查询URLError
,它说这会有一个reason
,这将是远程URL的socket.error
。 而且,如果您查找socket.error
它会告诉您它是IOError
或OSError
的子OSError
(取决于您的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,则可能移至诸如requests
或urllib3
类的第三方模块。 这两个库都有一个单独的Timeout
异常类型,而不是让您深入了解通用URLError
的详细信息。
签出requests
库。 如果您只想等待指定的时间(而不是整个下载,仅等到从服务器收到响应),只需将timeout
参数添加到标准URL请求中,以秒为单位:
r = requests.get(url, timeout=10)
如果超过了timeout
时间,则会引发requests.exceptions.Timeout
异常,可以根据需要进行处理。 例如,您可以将请求放在try / except块中,如果引发异常,则捕获该异常,然后在完全失败之前再次尝试连接指定的次数。
您可能还需要检出requests.adapters.HTTPAdapter
,它具有max_retries
参数。 它通常在Requests Session
,根据文档,它通过实现Transport Adapter接口为Requests会话提供了一个通用接口来联系HTTP和HTTPS url。
即使我是Python的新手,但我认为即使像这样的简单解决方案也可以解决问题,
首先将东西视为None,其中东西是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
希望能有所帮助。
问候,
莫辛博士
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.