异常

1.Python中,异常会根据错误自动地被触发,也能由代码主动触发和截获

2.捕捉异常的代码:

try:
    statements #该代码执行主要的工作,并有可能引起异常
except ExceptionType1: #except子句定义异常处理,这里捕捉特定的ExceptionType1类型的异常
    statements 
except (ExceptionType2,ExceptionType3): #except子句定义异常处理,
            #这里捕捉任何列出的异常(即只要是ExceptionType2类型或者ExceptionType3类型)
    statements 
except ExceptionType4 as excp: #这里捕捉特定的ExceptionType4类型异常,但是用变量名excp引用异常对象
    statements #这里可以使用excp引用捕捉的异常对象
except: # 该子句捕获所有异常
    statements
else: #如果没有发生异常,这来到这里;当发生了异常则不执行else子句
    statements
  • try子句执行时发生异常,则Python会执行第一个匹配该异常的except子句。当except子句执行完毕之后(除非该except子句 又引发了另一个异常),程序会跳转到整体语句之后执行。

    整体语句就是指上面的try..except..else

  • 如果异常发生在try代码块内,且无匹配的except子句,则异常向上传递到本try块外层的try块中。如果已经传递到了顶层了异常还没有被捕捉,则Python会终止程序并且打印默认的出错消息
  • 如果try代码块内语句未产生异常,则Python会执行else子句,然后程序会在整体语句之后继续执行

    try..except..else语句

3.try/finally语句:

try:
    statements
finally:
    statements

无论try代码块执行时是否发生了异常,finally子句一定会被执行

  • try子句无异常,则Python会接着执行finally子句,执行完之后程序会跳转到整体语句之后执行
  • try子句有异常,则Python会跳转到finally子句中,并接着把异常向上传递

    try..finally语句

4.Python中的try|except|finally统一格式:

try:
    statements #该代码执行主要的工作,并有可能引起异常
except ExceptionType1: #except子句定义异常处理,这里捕捉特定的ExceptionType1类型的异常
    statements 
except (ExceptionType2,ExceptionType3): #except子句定义异常处理,
            #这里捕捉任何列出的异常(即只要是ExceptionType2类型或者ExceptionType3类型)
    statements 
except ExceptionType4 as excp: #这里捕捉特定的ExceptionType4类型异常,但是用变量名excp引用异常对象
    statements #这里可以使用excp引用捕捉的异常对象
except:  # 该子句捕获所有异常
    statements
else:    # 如果没有发生异常,这来到这里;当发生了异常则不执行else子句
    statements
finally: # 一定会执行这个子句
    statements
  • elsefinally子句可选;except子句可能有0个或者多个。但是如果有else子句,则至少有一个except
  • finally执行时机:无论有没有异常抛出,在程序跳出整体语句之前的最后时刻一定会执行

    整体语句就是指上面的try..except..else...finally

    try..except...finally语句

5.要显式触发异常,可以用raise语句。有三种形式的形式:

  • raise exception_obj:抛出一个异常实例
  • raise Exception_type:抛出一个指定异常类型的实例,调用Exception_type()获得
  • raise <exceptionObj|Exception_type> from <exceptionObj2|Exception_type2>: 第二个异常实例会附加到第一个异常实例的.__cause__属性中并抛出第一个异常实例
  • raise:转发当前作用域中激活的异常实例。若当前作用域中没有激活的异常实例,则抛出RuntimeError实例对象

  • 一旦异常在程序中由某个except子句捕获,则它就死掉了不会再传递

  • raise抛出的必须是一个BaseException实例或者BaseException子类,否则抛出TypeError

    BaseException类是所有内建异常的父类。

    Exception类是所有内建异常、non-system-exiting异常的父类。用于自定义的异常类也应该从该类派生

    raise语句

    异常的死亡与活跃

6.在一个异常处理器内部raise一个异常时,前一个异常会附加到新异常的__context__属性

  • 如果在异常处理器内部raise被捕获的异常自己,则并不会添加到__context__属性

    异常处理器内的raise

  • 在异常处理器内部raiseraise e效果相同

    raise与raise e

7.assert语句可能会引起AssertionError。其用法为:assert <test>,<data>。这等价于:

if __debug__:
    if not <test>:    
    raise AssertionError(<data>)
  • <test>表达式用于计算真假,<data>表达式用于作为异常的参数。若<test>计算为假,则抛出AssertionError
  • 若执行时用命令行 -0标志位,则关闭assert功能(默认是打开的)。

    __debug__是内置变量名。当有-0标志位时,它为0;否则为1

  • 通常assert用于给定约束条件,而不是用于捕捉程序的错误。

    assert

8.Python3中有一种新的异常相关语句:with/as语句。它是作为try/finally的替代方案。用法为:

with expression [as var]:
    statements

expression必须返回一个对象,该对象必须支持环境管理协议。其工作方式为:

  • 计算expression表达式的值,得到环境管理器对象。环境管理器对象必须有.__enter__(self)方法和.__exit__(self, exc_type, exc_value, traceback)方法
  • 调用环境管理器对象的.__enter__(self)方法。如果有as子句,.__enter__(self)方法返回值赋值给as子句中的变量var;如果没有as子句,则.__enter__(self)方法返回值直接丢弃。并不是将环境管理器对象赋值给var
  • 执行statements代码块
  • 如果statements代码块抛出异常,则.__exit__(self, exc_type, exc_value, traceback)方法自动被调用

    在内部这几个实参由sys.exc_info()返回(exc_type, exc_value, traceback)信息,

    • .__exit__()方法返回值为False,则重新抛出异常到with语句之外
    • .__exit__()方法返回值为True,则异常终止于此,并不会抛出with语句之外
  • 如果statements代码块未抛出异常,则.__exit__(self, exc_type, exc_value, traceback)方法自动被调用,调用参数为:.__exit__(self,None,None,None)

    with语句

9.Python3.1之后,with语句可以指定多个环境管理器,以逗号分隔。根据定义的顺序这些环境管理器对象的.__enter__(self)方法顺序调用,.__exit__(self, exc_type, exc_value, traceback)方法逆序调用

如果对象要支持环境管理协议,则必须实现.__enter__(self)方法和.__exit__(self, exc_type, exc_value, traceback)方法

多个with