Python socket 错误恢复/解决方法
我有一个脚本在运行,它会测试一系列网址是否可用。
这是其中一个功能。
def checkUrl(url): # Only downloads headers, returns status code.
p = urlparse(url)
conn = httplib.HTTPConnection(p.netloc)
conn.request('HEAD', p.path)
resp = conn.getresponse()
return resp.status
有时候,虚拟专用服务器(VPS)会失去连接,这时整个脚本就会崩溃。
File "/usr/lib/python2.6/httplib.py", line 914, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python2.6/httplib.py", line 951, in _send_request
self.endheaders()
File "/usr/lib/python2.6/httplib.py", line 908, in endheaders
self._send_output()
File "/usr/lib/python2.6/httplib.py", line 780, in _send_output
self.send(msg)
File "/usr/lib/python2.6/httplib.py", line 739, in send
self.connect()
File "/usr/lib/python2.6/httplib.py", line 720, in connect
self.timeout)
File "/usr/lib/python2.6/socket.py", line 561, in create_connection
raise error, msg
socket.error: [Errno 101] Network is unreachable
我对在Python中处理这种错误一点都不熟悉。
当网络连接暂时中断时,有什么合适的方法可以防止脚本崩溃吗?
编辑:
我最后得到了这个 - 有什么反馈吗?
def checkUrl(url): # Only downloads headers, returns status code.
try:
p = urlparse(url)
conn = httplib.HTTPConnection(p.netloc)
conn.request('HEAD', p.path)
resp = conn.getresponse()
return resp.status
except IOError, e:
if e.errno == 101:
print "Network Error"
time.sleep(1)
checkUrl(url)
else:
raise
不过我不太明白raise到底是干什么的……
3 个回答
0
在你的代码周围加上 try
...except:
,这样可以捕捉到错误。
4
你现在这个解决方案有个问题,就是如果一个网址出现的错误太多(默认超过1000个),你会耗尽栈空间,因为你使用了递归。而且,额外的栈帧会让错误追踪变得难以阅读(比如调用了500次checkURL
)。我建议把它改成迭代的方式,像这样:
def checkUrl(url): # Only downloads headers, returns status code.
while True:
try:
p = urlparse(url)
conn = httplib.HTTPConnection(p.netloc)
conn.request('HEAD', p.path)
resp = conn.getresponse()
return resp.status
except IOError as e:
if e.errno == 101:
print "Network Error"
time.sleep(1)
except:
raise
另外,你在try
块中的最后一条语句应该是一个简单的except
,而不是else
。你的else
只有在try
块中的代码都执行完且没有遇到错误时才会执行,但这在这里是不可能的,因为try
块的最后一条语句是return
。
要让这个函数允许有限次数的重试其实很简单。只需要把while True:
这一行改成for _ in xrange(5)
,或者你想要的任何重试次数。这样,如果在5次尝试后仍然无法连接到网站,函数就会返回None
。你也可以让它返回其他东西或者抛出一个异常,只需在函数的最后加上return
或者raise SomeException
,并且缩进要和for
或while
那一行一样。
5
如果你只是想处理这个“网络无法访问 101”的错误,而让其他的错误继续抛出异常,你可以这样做,例如:
from errno import ENETUNREACH
try:
# tricky code goes here
except IOError as e:
# an IOError exception occurred (socket.error is a subclass)
if e.errno == ENETUNREACH:
# now we had the error code 101, network unreachable
do_some_recovery
else:
# other exceptions we reraise again
raise