1、什么是异常
python使用
异常对象
来表示异常状态,并在遇到错误时引发异常。异常对象未被处理或捕获时,程序将终止并显示一条错误消息(traceback)。如下:
>>> 1/0Traceback(most recent call last):File"<stdin>", line 1, in?ZeroDivisionError.integer division or modulo by zero
每个异常都是某个类(如ZeroDivisionError)的实例,我们可以以各种方式引发和捕获这些实例,从而逮住错误并采取措施,而不是放任整个程序失败。
2、引发和创建异常
raise语句引发异常:将一个类(必须是Exception的子类)或实例作为参数。
raise Exception # 将类作为参数时,将自动创建一个实例。这里引发的是通用异常,没有指出出现了什么错误。raise Exception(\'hyperdrive overload\') # 添加了错误消息hyperdrive overload
比较重要的一些内置的异常类:
Exception:几乎所有的异常类都是从它派生而来的AttributeError:引用属性或给他赋值失败时引发OSError:操作系统不能执行指定的任务(如打开文件)时引发,有多个子类indexError:使用序列中不存在的索引时引发,为LookupError的子类KeyError:使用映射中不存在的键时引发,为LookupError的子类NameError:找不到名称(或变量)时引发SyntaxError:代码不正确时引发TypeError:将内置操作或函数用于类型不正确的对象时引发ValueError:将内置操作或函数用于这样的对象时引发:其类型正确但包含的值不合适ZeroDivisionError:在除法或求模运算的第二个参数为0时引发
3、捕获异常
异常有趣的地方是可对其进行处理,称之为捕获异常。常用:try/except语句。基本用法:
# 一:捕获异常并对错误进行处理(打印友好的错误消息)try:x = int(input(\'first number:\'))y = int(input(\'second number:\'))print(x / y)except ZeroDivisionError:print("the second number can\'t be zero!")# 二:捕获异常后,抑制异常class MuffledCalculator:muffled = Falsedef calc(self, expr):try:return eval(expr)except ZeroDivisionError:if self.muffled: # 与用户交互时,启用抑制功能,不让异常继续传播print(\'Division by zero is illegal\')else: # 在程序内部使用时,关闭抑制功能,引发异常raise# 注意:发生除零行为,若启用抑制功,calc将隐式地返回None。# 三:在except子句中,引发别的异常try:1 / 0except ZeroDivisionError:raise ValueError # 进行except子句的异常将被作为异常上下文存储起来,并出现在最终的错误消息中# 四:使用None来禁用上下文try:1 / 0except ZeroDivisionError:raise ValueError from None# 执行结果如下:Traceback(most recent call last):File"<stdin>", line 3, in <module>ValueError
其他用法:
# 一、多个except子句,捕获多种异常try:x = int(input(\'first number:\'))y = int(input(\'second number:\'))print(x / y)except ZeroDivisionError:print("the second number can\'t be zero!")except TypeError:print("That wasn\'t a number, was it")# 二、一个except子句捕获多个异常,可在元组中指定异常(一个参数)try:x = int(input(\'first number:\'))y = int(input(\'second number:\'))print(x / y)except (ZeroDivisionError, TypeError, NameError):print("your numbers were bogus ...")# 三、捕获异常对象本身(可使用两个参数)try:x = int(input(\'first number:\'))y = int(input(\'second number:\'))print(x / y)except (ZeroDivisionError, TypeError) as e:print(e) # 打印异常并继续运行# 四、捕获所有异常,在except中不指定任何异常类即可try:x = int(input(\'first number:\'))y = int(input(\'second number:\'))print(x / y)except:print(\'something wrong happened ...\')# 这种做法很危险,会捕获到用户使用ctrl+c或调用函数sys.exit来终止执行的企图等。推荐使用except Exception as e对异常对象进行检查。(可能会让不是从Exception派生而来的异常漏网,如SystemExit、KeyboardInterrupt,他们是从Exception的超类BaseException派生而来)# 五、给try/except添加else子句和finally:没有出现异常时会执行else中代码块x = Nonetry:x = 1 / 0except NameError:print(\'unknown variable\')else:print("that went well!")finally:print("cleaning up...")del x # 发生异常时,执行finally子句清理工作(适用于确保文件或网络套接字等得以关闭)
4、异常之禅
很多情况下,相比使用if/else,使用try/except语句更自然,也更符合python风格。(直接去做,有问题在处理,而不是预先做大量的检查)