6-1-异常基础

1. 异常的角色

在 Python 中,异常通常可用于各种用途:

  • **错误处理。**每当在运行时检测到程序错误时,Python 就会引发异常。可以在程序代码中捕捉和响应错误,或者忽略已发生的异常。如果忽略错误,Python 默认的异常处理行为将启动:停止程序,打印出错消息。如果不想启动这种默认行为,就要写 try 语句来捕捉异常并从异常中恢复。
  • **事件通知。**异常也可用于发出有效状态的信号,而不需在程序间传递结果标志位,或者刻意对其进行测试。
  • **特殊情况处理。**有时发生某种很罕见的情况,很难调整代码去处理。通常会在异常处理器中处理这些罕见的情况,从而省去编写应对特殊情况的代码。
  • **终止行为。**try/finally 语句可确保一定会进行需要的结束运算,无论程序中是否有异常。
  • **非常规控制流程。**异常是一种高级的“goto”,它可以作为实现非常规的控制流程的基础。

2. 异常处理

2.1 默认异常处理器

当代码没有捕获异常时,它会一直向上返回到程序顶层,并启用默认的异常处理器,打印标准出错信息。

1
2
3
4
5
def fetcher(obj, index):
return obj[index]

x = 'spam'
fetcher(x, 4)
---------------------------------------------------------------------------

IndexError                                Traceback (most recent call last)

<ipython-input-3-0c1dd0f08fde> in <module>()
      3 
      4 x = 'spam'
----> 5 fetcher(x, 4)

<ipython-input-3-0c1dd0f08fde> in fetcher(obj, index)
      1 def fetcher(obj, index):
----> 2     return obj[index]
      3 
      4 x = 'spam'
      5 fetcher(x, 4)

IndexError: string index out of range

2.2 捕获异常

如果不想要默认的异常行为,就需要把调用包装在 try 语句内,自行捕捉异常:

1
2
3
4
try:
fetcher(x, 4)
except IndexError:
print('got exception')
got exception

try 语句不仅会捕捉异常,也会从中恢复执行:

1
2
3
4
5
6
7
8
def catcher():
try:
fetcher(x, 4)
except IndexError:
print('got exception')
print('continuing')

catcher()
got exception
continuing

2.3 引发异常

异常能由 Python 或程序引发,也能捕捉或忽略。要手动触发异常,直接执行 raise 语句:

1
raise IndexError
---------------------------------------------------------------------------

IndexError                                Traceback (most recent call last)

<ipython-input-6-55a00e7db5b5> in <module>()
----> 1 raise IndexError

IndexError: 

2.4 用户定义的异常

用户定义的异常能够通过类编写,它继承自一个内置的异常类:通常这个类的名称叫做 Exception。基于类的异常允许脚本建立异常类型、继承行为以及附加状态信息:

1
2
3
4
5
6
7
8
9
class AlreadyGotOne(Exception): pass

def grail():
raise AlreadyGotOne() # 引发一个实例

try:
grail()
except AlreadyGotOne:
print('got exception')
got exception

2.5 终止行为

try 语句可以包含 finally 代码块,可以定义一定会在最后执行时的收尾行为,无论 try 代码块中是否发生了异常:

1
2
3
4
try:
fetcher(x, 3)
finally:
print('after fetch')
after fetch