关于python:如何捕获多个异常?

How can I catch multiple exceptions?

本问题已经有最佳答案,请猛点这里访问。

我通常很擅长捕捉异常,但这群人让我困惑。下面是我正在使用的代码(它使用pywinrm):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import socket
def win_Upgrade_Check(kbByOS):
    for os in kbByOS:
        print(os)
        try:
            conn = winrm.Session(os, auth=("administrator","****"))
            for kb in kbByOS[os]:
                resp = conn.run_ps("get-hotfix -id {0}".format(kb))
                output = resp.std_out.decode('utf-8')
                error = resp.std_err
                if error:
                    print("KB{} not found on {}.".format(error,os))
                else:
                    print("{} found on {}.".format(kb,os))
        except timeout as e:
            print(e)
            pass

以下是我收到的错误呕吐词:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
Traceback (most recent call last):
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connection.py", line 142, in _new_conn
(self.host, self.port), self.timeout, **extra_kw)
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/util/connection.py", line 91, in create_connection
    raise err
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/util/connection.py", line 81, in create_connection
    sock.connect(sa)
socket.timeout: timed out

Traceback (most recent call last):
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connection.py", line 142, in _new_conn
(self.host, self.port), self.timeout, **extra_kw)
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/util/connection.py", line 91, in create_connection
    raise err
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/util/connection.py", line 81, in create_connection
    sock.connect(sa)
socket.timeout: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py", line 578, in urlopen
    chunked=chunked)
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py", line 362, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File"/usr/lib/python3.5/http/client.py", line 1106, in request
    self._send_request(method, url, body, headers)
  File"/usr/lib/python3.5/http/client.py", line 1151, in _send_request
    self.endheaders(body)
  File"/usr/lib/python3.5/http/client.py", line 1102, in endheaders
    self._send_output(message_body)
  File"/usr/lib/python3.5/http/client.py", line 934, in _send_output
    self.send(msg)
  File"/usr/lib/python3.5/http/client.py", line 877, in send
    self.connect()
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connection.py", line 167, in connect
    conn = self._new_conn()
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connection.py", line 147, in _new_conn
    (self.host, self.timeout))
requests.packages.urllib3.exceptions.ConnectTimeoutError: (<requests.packages.urllib3.connection.HTTPConnection object at 0x7fc019afed30>, 'Connection to **** timed out. (connect timeout=30)')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File"/usr/local/lib/python3.5/dist-packages/requests/adapters.py", line 403, in send
    timeout=timeout
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/connectionpool.py", line 623, in urlopen
    _stacktrace=sys.exc_info()[2])
  File"/usr/local/lib/python3.5/dist-packages/requests/packages/urllib3/util/retry.py", line 281, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
requests.packages.urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='****', port=5985): Max retries exceeded with url: /wsman (Caused by ConnectTimeoutError(<requests.packages.urllib3.connection.HTTPConnection object at 0x7fc019afed30>, 'Connection to **** timed out. (connect timeout=30)'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File"bulletin_parse.py", line 258, in <module>
    win_Upgrade_Check(kbByOS)
  File"bulletin_parse.py", line 247, in win_Upgrade_Check
    resp = conn.run_ps("get-hotfix -id {0}".format(kb))
  File"/usr/local/lib/python3.5/dist-packages/winrm/__init__.py", line 54, in run_ps
    rs = self.run_cmd('powershell -encodedcommand {0}'.format(encoded_ps))
  File"/usr/local/lib/python3.5/dist-packages/winrm/__init__.py", line 41, in run_cmd
    shell_id = self.protocol.open_shell()
  File"/usr/local/lib/python3.5/dist-packages/winrm/protocol.py", line 132, in open_shell
    res = self.send_message(xmltodict.unparse(req))
  File"/usr/local/lib/python3.5/dist-packages/winrm/protocol.py", line 207, in send_message
    return self.transport.send_message(message)
  File"/usr/local/lib/python3.5/dist-packages/winrm/transport.py", line 173, in send_message
    response = self.session.send(prepared_request, timeout=self.read_timeout_sec)
  File"/usr/local/lib/python3.5/dist-packages/requests/sessions.py", line 585, in send
    r = adapter.send(request, **kwargs)
  File"/usr/local/lib/python3.5/dist-packages/requests/adapters.py", line 459, in send
    raise ConnectTimeout(e, request=request)
requests.exceptions.ConnectTimeout: HTTPConnectionPool(host='****', port=5985): Max retries exceeded with url: /wsman (Caused by ConnectTimeoutError(<requests.packages.urllib3.connection.HTTPConnection object at 0x7fc019afed30>, 'Connection to **** timed out. (connect timeout=30)'))

正如您在我当前的代码中看到的,我首先尝试捕获socket.timeout。我也试着把它改为除e之外的例外,认为"一网打尽"甚至比我现在拥有的更好,但也失败了。我尝试编辑transport.py为requests.exceptions.connectTimeout添加一个异常,但这也无法捕获它。

是否有一些特殊的事情需要做,因为它的多个例外发生?


您可以根据需要添加任意多个不同的异常:

1
2
3
4
5
6
7
8
try:
    doMyFavoriteThing()
except ValueError:
    print"Whoops!"
except timeout:
    print"Whoopsies!"
except MaxRetryError:
    print"Whoopsie daisies!"

或者,如果要捕获所有异常,因为所有异常都是Exception类的子类,可以这样做:

1
2
3
4
try:
    doMyFavoriteThing()
except Exception as e:
    print str(e)

当然,第一种方法通常被认为是更好的——您可能会发现其他格式的名称错误或其他愚蠢的错误。


回答你的第一个问题:如何捕获多个异常?

您可以这样简单地嵌套异常:

(来自python文档。https://docs.python.org/3/tutorial/errors.html处理异常)

1
2
3
4
5
6
7
8
9
10
11
12
13
import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error: {0}".format(err))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise

首先,如果没有'myfile.txt',将抛出第一个异常。它看起来像:IOError [Errno2] No such file or directory: 'myfile.txt'

如果有这样一个文件但没有内容,那么第二个异常将被抛出等等。

但是,为了帮助您解决第二个问题:没有抛出socket.timeout错误,您应该将异常更改为socket.timeout类型。

因此,将代码更改为:

1
2
    except socket.timeout as e:
        print(e)

这应该能解决你的问题。