我正在尝试强制Python在我收到超时错误时重试加载页面。有没有办法可以让它重试特定次数,可能是在特定的时间延迟之后?
任何帮助都将不胜感激。
谢谢。
答案 0 :(得分:3)
urllib2
没有内置任何内容,但您可以自己编写。
棘手的部分是,正如urlopen
文档所说,无论出现什么问题,你只需要URLError
。那么,你怎么知道它是暂停还是其他什么?
好吧,如果您查找URLError
,它会说reason
对于远程网址是socket.error
。如果你查找socket.error
,它会告诉你它是IOError
或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
的详细信息。
答案 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
希望有所帮助。
此致
马里兰州穆赫辛