语法错误

如下,当我们编写的代码中出现语法错误的时候,Python 解析器会报这类的错误。

>>> while True print('Hello world')
  File "<stdin>", line 1
    while True print('Hello world')
                   ^
SyntaxError: invalid syntax
1
2
3
4
5

异常

在程序运行过程中,难免会出现异常。下面展示了几种运行时异常。

>>> 10 * (1/0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
1
2
3
4
5
6
7
8
9
10
11
12

处理异常

我们通过 try 语句来处理异常,完成的使用方法如下:

try:
    <statement-1>
    .
    .
    <statement-N>
except Exception as err:
    <statement>
except (RuntimeError, TypeError, NameError):
    <statement>
else:
    <statement>
finally:
    <statement>
1
2
3
4
5
6
7
8
9
10
11
12
13

首先执行 tryexcept 之间的语句,如果未出现异常,则 try 语句执行结束。否则,会逐个匹配 except 语句,匹配上则执行 except 语句,否则会继续抛出异常。except Except as err,我们可以通过 err 来访问异常对象,我们可以通过 err.args 来访问构造这个异常对象时的参数。

else 语句在 try 中执行完,且没有出现异常的时候执行。finally 语句指定了在 try 返回之前要做的事情,不管是否有异常发生,通常会被用来做一些收尾工作,比如关闭文件等。如果 finally 语句中指定了 return 语句,那么 finallyreturn 的会替换掉 tryreturn 的值。

抛出异常

我们可以通过 raise 语句抛出一个异常。

>>> try:
...     raise NameError('HiThere')
... except NameError as err:
...     print('An exception flew by!' + str(err.args))
...     raise
...
An exception flew by! ('HiThere',)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
NameError: HiThere
1
2
3
4
5
6
7
8
9
10

raise 语句还支持后跟一个 from 语句来实现异常的级联。

>>> def func():
...     raise IOError
...
>>> try:
...     func()
... except IOError as exc:
...     raise RuntimeError('Failed to open database') from exc
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in func
OSError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: Failed to open database
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

通过异常级联,我们可以清楚的看出异常抛出的链路。

注意,在 except 语句和 finally 语句中抛出的异常是自动级联的。

>>> try:
...     raise NameError('aa')
... except NameError as err:
...     raise RuntimeError from err
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
NameError: aa

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError
1
2
3
4
5
6
7
8
9
10
11
12
13
14

前面说到,finally 语句可以用来处理异常发生后的收尾工作。但是很多时候会显得比较繁琐,比如读写文件的时候,如果忘记在 finally 语句中关闭文件,则会导致内存泄漏等严重问题。

我们可以通过 with 语句来帮助我们自动处理这些收尾工作,使得代码更加简洁。

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")
1
2
3

当然,with 语句不是所有地方都能用。要使用 with 语句,需实现 __enter____exit__ 方法,具体细节可以看这里open in new window

关注微信公众号,获取最新推送~