|
| 1 | +<!-- |
| 2 | + 作者:华校专 |
| 3 | + email: huaxz1986@163.com |
| 4 | +** 本文档可用于个人学习目的,不得用于商业目的 ** |
| 5 | +--> |
| 6 | +# 异常 |
| 7 | +1.Python中,异常会根据错误自动地被触发,也能由代码主动触发和截获 |
| 8 | + |
| 9 | +2.捕捉异常的代码: |
| 10 | + |
| 11 | +``` |
| 12 | +try: |
| 13 | + statements #该代码执行主要的工作,并有可能引起异常 |
| 14 | +except ExceptionType1: #except子句定义异常处理,这里捕捉特定的ExceptionType1类型的异常 |
| 15 | + statements |
| 16 | +except (ExceptionType2,ExceptionType3): #except子句定义异常处理, |
| 17 | + #这里捕捉任何列出的异常(即只要是ExceptionType2类型或者ExceptionType3类型) |
| 18 | + statements |
| 19 | +except ExceptionType4 as excp: #这里捕捉特定的ExceptionType4类型异常,但是用变量名excp引用异常对象 |
| 20 | + statements #这里可以使用excp引用捕捉的异常对象 |
| 21 | +except: # 该子句捕获所有异常 |
| 22 | + statements |
| 23 | +else: #如果没有发生异常,这来到这里;当发生了异常则不执行else子句 |
| 24 | + statements |
| 25 | +``` |
| 26 | + |
| 27 | +* 当`try`子句执行时发生异常,则Python会执行第一个匹配该异常的`except`子句。当`except`子句执行完毕之后(除非该`except`子句 又引发了另一个异常),程序会跳转到整体语句之后执行。 |
| 28 | + >整体语句就是指上面的`try..except..else` |
| 29 | +* 如果异常发生在`try`代码块内,且无匹配的`except`子句,则异常向上传递到本`try`块外层的`try`块中。如果已经传递到了顶层了异常还没有被捕捉,则Python会终止程序并且打印默认的出错消息 |
| 30 | +* 如果`try`代码块内语句未产生异常,则Python会执行`else`子句,然后程序会在整体语句之后继续执行 |
| 31 | + |
| 32 | +  |
| 33 | + |
| 34 | +3.`try/finally`语句: |
| 35 | + |
| 36 | +``` |
| 37 | +try: |
| 38 | + statements |
| 39 | +finally: |
| 40 | + statements |
| 41 | +``` |
| 42 | +无论`try`代码块执行时是否发生了异常,`finally`子句一定会被执行 |
| 43 | + |
| 44 | +* 若`try`子句无异常,则Python会接着执行`finally`子句,执行完之后程序会跳转到整体语句之后执行 |
| 45 | +* 若`try`子句有异常,则Python会跳转到`finally`子句中,并接着把异常向上传递 |
| 46 | + |
| 47 | +  |
| 48 | + |
| 49 | +4.Python中的`try|except|finally`统一格式: |
| 50 | + |
| 51 | +``` |
| 52 | +try: |
| 53 | + statements #该代码执行主要的工作,并有可能引起异常 |
| 54 | +except ExceptionType1: #except子句定义异常处理,这里捕捉特定的ExceptionType1类型的异常 |
| 55 | + statements |
| 56 | +except (ExceptionType2,ExceptionType3): #except子句定义异常处理, |
| 57 | + #这里捕捉任何列出的异常(即只要是ExceptionType2类型或者ExceptionType3类型) |
| 58 | + statements |
| 59 | +except ExceptionType4 as excp: #这里捕捉特定的ExceptionType4类型异常,但是用变量名excp引用异常对象 |
| 60 | + statements #这里可以使用excp引用捕捉的异常对象 |
| 61 | +except: # 该子句捕获所有异常 |
| 62 | + statements |
| 63 | +else: # 如果没有发生异常,这来到这里;当发生了异常则不执行else子句 |
| 64 | + statements |
| 65 | +finally: # 一定会执行这个子句 |
| 66 | + statements |
| 67 | +``` |
| 68 | +* `else`、`finally`子句可选;`except`子句可能有0个或者多个。但是如果有`else`子句,则至少有一个`except` |
| 69 | +* `finally`执行时机:无论有没有异常抛出,在程序跳出整体语句之前的最后时刻一定会执行 |
| 70 | + >整体语句就是指上面的`try..except..else...finally` |
| 71 | + |
| 72 | +  |
| 73 | + |
| 74 | +5.要显式触发异常,可以用`raise`语句。有三种形式的形式: |
| 75 | + |
| 76 | +* `raise exception_obj`:抛出一个异常实例 |
| 77 | +* `raise Exception_type`:抛出一个指定异常类型的实例,调用`Exception_type()`获得 |
| 78 | +* `raise <exceptionObj|Exception_type> from <exceptionObj2|Exception_type2>`: |
| 79 | + 第二个异常实例会附加到第一个异常实例的`.__cause__`属性中并抛出第一个异常实例 |
| 80 | +* `raise`:转发当前作用域中激活的异常实例。若当前作用域中没有激活的异常实例,则抛出`RuntimeError`实例对象 |
| 81 | + |
| 82 | +* 一旦异常在程序中由某个`except`子句捕获,则它就死掉了不会再传递 |
| 83 | +* `raise`抛出的必须是一个`BaseException`实例或者`BaseException`子类,否则抛出`TypeError` |
| 84 | + >`BaseException`类是所有内建异常的父类。 |
| 85 | + > |
| 86 | + >`Exception`类是所有内建异常、`non-system-exiting`异常的父类。用于自定义的异常类也应该从该类派生 |
| 87 | + |
| 88 | +  |
| 89 | + |
| 90 | +  |
| 91 | + |
| 92 | +6.在一个异常处理器内部`raise`一个异常时,前一个异常会附加到新异常的`__context__`属性 |
| 93 | + |
| 94 | +* 如果在异常处理器内部`raise`被捕获的异常自己,则并不会添加到`__context__`属性 |
| 95 | + |
| 96 | +  |
| 97 | + |
| 98 | +* 在异常处理器内部`raise`与`raise e`效果相同 |
| 99 | + |
| 100 | +  |
| 101 | + |
| 102 | +7. `assert`语句可能会引起`AssertionError`。其用法为:`assert <test>,<data>`。这等价于: |
| 103 | + |
| 104 | +``` |
| 105 | +if __debug__: |
| 106 | + if not <test>: |
| 107 | + raise AssertionError(<data>) |
| 108 | +``` |
| 109 | + |
| 110 | +* `<test>`表达式用于计算真假,`<data>`表达式用于作为异常的参数。若`<test>`计算为假,则抛出`AssertionError` |
| 111 | +* 若执行时用命令行 `-0`标志位,则关闭`assert`功能(默认是打开的)。 |
| 112 | + > `__debug__`是内置变量名。当有`-0`标志位时,它为0;否则为1 |
| 113 | +* 通常`assert`用于给定约束条件,而不是用于捕捉程序的错误。 |
| 114 | + |
| 115 | +  |
| 116 | + |
| 117 | +8.Python3中有一种新的异常相关语句:`with/as`语句。它是作为`try/finally`的替代方案。用法为: |
| 118 | + |
| 119 | +``` |
| 120 | +with expression [as var]: |
| 121 | + statements |
| 122 | +``` |
| 123 | +`expression`必须返回一个对象,该对象必须支持环境管理协议。其工作方式为: |
| 124 | + |
| 125 | +* 计算`expression`表达式的值,得到环境管理器对象。环境管理器对象必须有`.__enter__(self)`方法和`.__exit__(self, exc_type, exc_value, traceback)`方法 |
| 126 | +* 调用环境管理器对象的`.__enter__(self)`方法。如果有`as`子句,`.__enter__(self)`方法返回值赋值给`as`子句中的变量`var`;如果没有`as`子句,则`.__enter__(self)`方法返回值直接丢弃。**<font color='red'>并不是将环境管理器对象赋值给`var`</font>** |
| 127 | +* 执行`statements`代码块 |
| 128 | +* 如果`statements`代码块抛出异常,则`.__exit__(self, exc_type, exc_value, traceback)`方法自动被调用 |
| 129 | + >在内部这几个实参由`sys.exc_info()`返回`(exc_type, exc_value, traceback)`信息, |
| 130 | + |
| 131 | + * 若`.__exit__()`方法返回值为`False`,则重新抛出异常到`with`语句之外 |
| 132 | + * 若`.__exit__()`方法返回值为`True`,则异常终止于此,并不会抛出`with`语句之外 |
| 133 | +* 如果`statements`代码块未抛出异常,则`.__exit__(self, exc_type, exc_value, traceback)`方法自动被调用,调用参数为:`.__exit__(self,None,None,None)` |
| 134 | + |
| 135 | +  |
| 136 | + |
| 137 | +9.Python3.1之后,`with`语句可以指定多个环境管理器,以逗号分隔。根据定义的顺序这些环境管理器对象的`.__enter__(self)`方法顺序调用,`.__exit__(self, exc_type, exc_value, traceback)`方法逆序调用 |
| 138 | +>如果对象要支持环境管理协议,则必须实现`.__enter__(self)`方法和`.__exit__(self, exc_type, exc_value, traceback)`方法 |
| 139 | +
|
| 140 | +  |
| 141 | + |
| 142 | + |
0 commit comments