1.2.8. Python 中的异常处理¶
如果您键入了本教程中之前的所有命令,则很可能已经引发了异常。例如,如果您输入的命令有错别字,则可能会引发异常。
异常是由执行 Python 代码时出现的各种错误引发的。在您自己的代码中,您也可以捕获错误或定义自定义错误类型。在查找正确的异常类型时,您可能需要查看内置异常的描述。
1.2.8.1. 异常¶
异常是由 Python 中的错误引发的
In [1]: 1/0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Cell In[1], line 1
----> 1 1/0
ZeroDivisionError: division by zero
In [2]: 1 + 'e'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[2], line 1
----> 1 1 + 'e'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
In [3]: d = {1:1, 2:2}
In [4]: d[3]
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[4], line 1
----> 1 d[3]
KeyError: 3
In [5]: l = [1, 2, 3]
In [6]: l[4]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[6], line 1
----> 1 l[4]
IndexError: list index out of range
In [7]: l.foobar
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[7], line 1
----> 1 l.foobar
AttributeError: 'list' object has no attribute 'foobar'
如您所见,针对不同的错误,存在**不同类型**的异常。
1.2.8.2. 捕获异常¶
try/except¶
In [8]: while True:
...: try:
...: x = int(input('Please enter a number: '))
...: break
...: except ValueError:
...: print('That was no valid number. Try again...')
...:
Please enter a number: a
That was no valid number. Try again...
Please enter a number: 1
In [9]: x
Out[9]: 1
try/finally¶
In [10]: try:
....: x = int(input('Please enter a number: '))
....: finally:
....: print('Thank you for your input')
....:
Please enter a number: a
Thank you for your input
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[10], line 2
1 try:
----> 2 x = int(input('Please enter a number: '))
3 finally:
4 print('Thank you for your input')
ValueError: invalid literal for int() with base 10: 'a'
对于资源管理(例如关闭文件)非常重要
寻求宽恕比寻求许可更容易¶
In [11]: def print_sorted(collection):
....: try:
....: collection.sort()
....: except AttributeError:
....: pass # The pass statement does nothing
....: print(collection)
....:
In [12]: print_sorted([1, 3, 2])
[1, 2, 3]
In [13]: print_sorted(set((1, 3, 2)))
{1, 2, 3}
In [14]: print_sorted('132')
132
1.2.8.3. 引发异常¶
捕获和重新引发异常
In [15]: def filter_name(name): ....: try: ....: name = name.encode('ascii') ....: except UnicodeError as e: ....: if name == 'Gaël': ....: print('OK, Gaël') ....: else: ....: raise e ....: return name ....: In [16]: filter_name('Gaël') OK, Gaël Out[16]: 'Gaël' In [17]: filter_name('Stéfan') --------------------------------------------------------------------------- UnicodeEncodeError Traceback (most recent call last) Cell In[17], line 1 ----> 1 filter_name('Stéfan') Cell In[15], line 8, in filter_name(name) 6 print('OK, Gaël') 7 else: ----> 8 raise e 9 return name Cell In[15], line 3, in filter_name(name) 1 def filter_name(name): 2 try: ----> 3 name = name.encode('ascii') 4 except UnicodeError as e: 5 if name == 'Gaël': UnicodeEncodeError: 'ascii' codec can't encode character '\xe9' in position 2: ordinal not in range(128)
异常用于在代码的不同部分之间传递消息
In [18]: def achilles_arrow(x): ....: if abs(x - 1) < 1e-3: ....: raise StopIteration ....: x = 1 - (1-x)/2. ....: return x ....: In [19]: x = 0 In [20]: while True: ....: try: ....: x = achilles_arrow(x) ....: except StopIteration: ....: break ....: ....: In [21]: x Out[21]: 0.9990234375
使用异常来通知某些条件是否满足(例如 StopIteration)或不满足(例如自定义错误引发)