Python套接字错误恢复/变通方法

时间:2011-10-31 07:01:15

标签: python sockets networking

我有一个正在运行的脚本,正在测试一系列可用的网址。

这是其中一项功能。

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

我不确定我是否完全明白加注的内容..

3 个答案:

答案 0 :(得分:4)

如果由于递归导致单个URL上的错误太多(默认情况下为> 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。您可以通过在函数的最后添加returnraise SomeException来使其返回其他内容或引发异常(缩进与forwhile行相同)

答案 1 :(得分:3)

如果您只想处理此网络无法访问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

答案 2 :(得分:0)

try ... except:放在您的代码周围以捕获异常。

http://docs.python.org/tutorial/errors.html