异常
异常基础
默认的异常处理器:
异常会向上返回到程序顶层,启用默认的异常处理器,打印标准出错消息(堆栈跟踪和引发的异常)并终止程序.
异常的角色:
错误处理,事件通知,特殊情况处理,终止行为,非常规流程控制
异常产生:
python引发
raise语句:
显式的触发异常,raise关键字后跟着可选的要引发的异常类或者异常类的一个实例(异常总是类的实例)
raise接受任何类型的对象引用
传递异常:raise不包括异常名称或额外数据值时,就重新引发当前异常
异常链:可选的from子句,指定了另一个异常类或实例,附加到引发异常的
__cause__
属性.如果引发的异常没有捕获,python也将其作为标准出错消息的一部分.异常处理器内部引发一个异常时,将前一个异常附加到新的异常的
__context__
属性例子:
excs = [IndexError, TypeError] try: raise excs[0]('附加信息') # 列表引用,抛出异常时增加提示信息 except: raise # 重新引发IndexError异常 except IndexError as e raise TypeError('Bad!') from e # from异常链 ,IndexError异常也会输出
assert语句(断言):
可视为条件式的raise,其后的条件为假时,抛出AssertionError异常
形式为’assert [,]’,项是异常的额外数据
附加的功能,使用-0 pyhon命令行标志位,类似
python-0 main.py
就会从程序编译后的字节码中移除,优化程序,关闭assert.用来收集用户定义的约束条件
异常处理:
try: # 标记当前的程序环境,发生异常时返回,执行第一个符合引发异常的except子句下的语句
<statements>
except <name1>: # 捕捉特定的异常.可以有多个except子句,从上到下,从左到右查看except子句
<statements>
except (name1,name2): # 捕捉任何列出的异常
<statements>
except <name4> as <data>: # 捕捉异常,并将变量名称分配给其实例化对象,可以访问实例中的数据和异常类中的方法
<statements>
except: # 捕捉所有异常类型.
<statements>
else: # 如果没有异常,就执行.有至少一个except存在才能存在
<statements>
finally: # 无论是否发生异常,都执行.与except子句必须有其一.
<statements>
with/as环境管理器:
用于定义必须执行的终止或’清理’行为,无论处理步骤中是否发生异常.支持丰富的基于对象的协议,可以为代码块定义支持进入和离开动作.强化一些内置工具,例如自动关闭文件,自动上锁开锁.
基本格式:
with expression [as variable][,expression [as variable]]: # expression返回一个对象,支持环境管理协议,可以用逗号语法指定多个
with-block
环境管理协议:
环境管理器对象必须有
__enter__
和__exit__
方法__enter__
方法一开始会被调用,如果as子句存在,返回值赋值给as子句中的变量,否则,丢弃(所以variable不一定是环境管理器对象,但很多情况下,__enter__
返回的是self对象本身)with代码块引发异常,
__exit__(type, value, traceback)
方法就会被调用,参数为sys.exc_info的返回值.__exit__
返回值为假时,异常会重新引发,传递到with语句外面.否则,会终止.默认返回None,为假.with代码块执行完没有异常也会调用
__exit__
,其参数都为None.
异常对象
基于类的异常特点:
提供类型分类,对今后的修改有了更好的支持.用户通过类自定义异常,继承自内置异常类(Exception),用户定义的异常类最好有一个超类,包含其他的子类.
附加了状态信息.sys.exc_info和异常实例的
__class__
属性可以识别具体异常类型支持继承.超类可以捕捉子类的异常.
内置异常类层次结构:
BaseException # 异常的顶级根类
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception # 与应用相关的异常的顶级根类,定义用户异常类时,这里继承
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
默认打印和状态:
传递给异常类的任何构造函数参数都会保存在args元祖属性中,打印该实例时自动显示.
异常的设计
异常的嵌套:
python会挑选并执行具有相符的except最近的try
异常的习惯用法:
所有的错误都是异常,但异常不总是错误,可作为信号
函数信号条件,用于无法返回警示值以表明成功或失败的函数
关闭文件或服务连接
在try外进行调试:通过循环,except执行测试,错误发生后,仍保持函数处于激活状态,执行其他测试
sys.exc_info返回一个(异常类型, 异常值/实例,traceback追踪对象)的三元祖
异常有关技巧:
捕捉过多:避免空except语句,会拦截到无关的系统异常.具体优于一般,具体容易处理.意图明显
捕捉过少:使用基于类的分类.捕捉一般的超类,就可以新增和引发更为特定的子类,超类变成可扩展的异常分类.