异常处理Python程序设计
目录2第一节异常的概念第二节异常的抛出与捕获第三节自定义异常第四节使用断言
第一节异常的概念
异常的概念通过前面第3章内容的学习,我们了解了Python中的三大程序控制流程:顺序结构、选择结构和循环结构。然而,在程序运行过程中不免会因为程序内在缺陷或者用户使用不当(例如,除法运算时以0作为除数,用户输入不符合规范等)而无法按照预定的控制流程运行下去。这种在程序运行时产生的例外、违例情况被称为异常(Exception)。如果不能在异常发生时及时妥善地处理它们,程序将崩溃,无法继续运行下去。4
异常的概念为了提高程序的鲁棒性,大多数高级程序设计语言都提供了完善的异常处理机制。当程序出现异常时,预先定义好的异常处理策略将为程序提供一个“安全通道”,修正程序中的错误以使程序能够继续运行下去,或当错误无法被修正时做使程序终止前的必要工作。在Python中,异常是以对象的形式实现的。BaseException类是所有异常类的基类,而其子类Exception类则是除了SystemExit、GeneratorExit和KeybaordInterrupt三个系统级异常之外所有内置异常类和用户自定义异常类的基类。5
常见的标准异常6
第二节异常的抛出与捕获
使用raise关键字抛出异常如前所述,程序在运行过程中出现错误而无法正常运行时,会陷入异常。此外,Python也为用户提供了raise关键字以人为地抛出指定类型的异常。raise语句的基本语法非常简单,下面这行代码展示了如何使用raise语句抛出一个除0异常:执行该语句会在控制台产生以下输出,表示程序中有未处理的异常:使用raise语句手动抛出异常在程序调试、自定义异常等场景下有诸多应用。注意,Python不会自动引发自定义异常,这要求程序开发者为自定义的异常编写合理的异常抛出代码(即在合理的场合,使用raise语句抛出合理的自定义异常),本书将在下一节中继续讨论这一问题。8
使用try...except捕获异常当异常发生时,就需要捕获并处理相应的异常。try...except语句是捕获处理异常的常用语句之一9其中,except子句可以有多个,当try后的语句执行时发生异常,Python就跳过try代码段余下的部分,执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try...except语句(除非在处理异常时又引发新的异常)。Python亦提供了较为灵活的语法,except后面可以放置多个异常类型(以逗号分割)以表明若多个异常中至少发生一个,则执行该部分异常处理代码,若不放置任何异常类型,则代表可匹配所有的异常类型。Python语句try:语句#可能的异常except异常类型:语句#发生异常时执行
使用try...except捕获异常的例子10try代码段首先抛出了IOError异常,Python会跳过第3行中输出“try”的语句,直接跳转到except子句,并依次匹配except子句所指明的异常类型:由于IOError不是第一条except语句所指明的两种异常类型(ZeroDivisionError和IndexError)故被跳过,而IOError是BaseException类的子类,故其为该类型异常,第二个except子句的代码段会被执行,输出exception2,至此异常处理完成
使用try...except捕获异常的例子11fun2函数第一次调用fun1函数时,fun1函数抛出OSError异常,由于该异常没有被捕获因而被递交到了上层函数fun2,嵌套在内层的try...except也未能捕获该异常,将其递交给外层的try...except语句,异常被外层的try...except语句捕获并处理。fun2函数第二次调用fun函数时,被抛出的异常没有被任何异常处理语句捕获,因而被递交到程序最上层,致使程序终止,并打印默认的异常信息。
使用else和finally子句处理异常12Python还为用户提供了else和finally两个子句,以用于try…except异常处理语句。如果try代码段中没有任何异常发生,则执行else子句后的代码,而finally子句中的代码段会无条件执行。Python语句try:可能抛出异常的代码段except[(Exception1[,Exception2[,...ExceptionN]]])]:若发生以上多个异常中的一个,则执行这块代码else:若没有异常,则执行这块代码finally:无论异常是否发生均执行该块代码
第三节自定义异常
自定义异常14