1.try/except
捕捉由Python或你引起的异常并恢复。
try/finally
无论异常是否发生,执行清理行为。
raise
手动在代码中触发异常
assert
有条件地在程序代码中触发异常。
with/as
在python2.6和后续版本中实现环境管理器(在2.5版中是可选功能)
2.assert语句也可以用来触发异常--是一个有条件的raise,主要是在开发过程中用于调试。
3.用户定义的异常能够通过类编写,它继承自一个内置的异常类:通常这个类的名称叫做Exception。基于类的异常允许脚本建立异常类型、继承行为以及附加状态信息。
4.使用try/except来捕捉从第三方库导入的代码所引发的错误,然后以try/finally来确保关闭文件,或者终止服务器连接的调用等行为一定会执行。
finally一定会执行,无论是否有异常引发,而且也不管异常是否被except子句捕捉到。
with/as运行一个对象的环境管理逻辑,来确保终止行为的发生。
5.小结:try语句有两种逻辑形式,可以组合起来,一种处理异常,一种不管是否发生异常都执行最终代码。raise和assert语句根据需要触发异常(都是内置函数,并且都是我们用类定义的新异常);with/as是一种替代方式,确保对它所支持的对象执行终结操作。
异常编码细节
1.try语句分句形式
try:
<statements>
except <name1>:
<statements>
except(name2,name3):
<statements>
except <name4> as <data>:
<statements>
except:
<statements>
else:
<statements>
2.try/finally分句
try:
<statements>
finally:
<statements>
如果try时没有异常发生,会跳至执行finally代码块,然后在整个try语句后继续执行下去。
如果有异常发生,依然会运行finally代码,但是会把异常向上传递到较高的try语句或顶层默认处理器。程序不会再try语句下继续执行。与except不同的就是finally不会终止异常。
3.try/except/finally
try:
main-action
except Exception1:
handler1
except Exception2:
handler2
...
else:
else-block
finally:
finally-block
可选部分:
try:
statements
except [type [as value]]:
statements
[except [type [as value]]:
statements]*
[else:
statements]
[finally:
statements]
4.raise
raise <instance>
raise <class>
raise IndexError #class
raise IndexError() #instance
exc = IndexError()
raise exc
excs = [IndexError,TypeError]
raise excs[0]
5.python3.0异常链:raise from
raise exception from otherexception
第二个表达式指定了另一个异常类或实例,它会附加到引发异常的__cause__属性。
3.0不支持raise Exc,Args形式。
当在一个异常处理器内部引发一个异常的时候,隐式地遵从类似的过程:前一个异常附加到新的异常的__context__属性,并且如果该异常未捕获的话,再次显示在标准出错信息中。
6.assert
条件式的raise语句
assert <test>,<data>
通常用于验证开发期间程序状况的。
assert几乎都是用来收集用户定义的约束条件
7.with/as环境管理器
激活:
from __future__ import with _statement
作为try/finally常见的替代方案。
with语句支持更丰富的基于对象的协议,可以为代码块定义支持进入和离开动作。
with expression [as variable]:
with-block
可以自己编写环境管理器。
支持逗号:
with A() as a,B() as b:
...statement...
with A() as a:
with B() as b:
...statement..
8.小结:try是捕捉,raise是触发,assert是条件式引发,with是把代码块包装在环境管理器中(定义了进入和离开的行为)。
异常分类
class General(Exception):pass
class Specific1(General):pass
class Specific2(General):pass
def raiser0():
X = General()
raise X
def raiser1():
X = Specific1()
raise X
def raiser2():
X = Specific2()
raise X
for func in (raiser0,raiser1,raiser2):
try:
func()
except General:
import sys
print('caught:',sys.exc_info()[0])
# except General as X:
# print('caught:',X.__class__)
caught: <class '__main__.General'>
caught: <class '__main__.Specific1'>
caught: <class '__main__.Specific2'>
·sys.exc_info调用:这是一种抓取最近发生异常的常用方式。等价于获取实例的__class__属性。
对于基于类的异常而言,结果中的第一个元素是引发异常类,第二个是实际引发的实例。
内置Exception类
1.BaseException
异常的顶级根类。不能由用户定义类直接继承。提供了子类所继承的默认的打印和状态保持行为。
实例构造时传给这个类的所有参数都作为元组存储于其args属性中。
2.Exception
与应用相关的异常的顶层根超类。是BaseException的一个直接子类。并且是所有其他内置异常的超类,除了系统推出事件类之外(SystemExit、KeyboardInterrupt、GeneratorExit)
3.ArithmeticError
所有数值错误的超类(并且是Exception的一个子类)
子类:OverflowErro、ZeroDivisionError
4.OverflowError
是被特定的数值错误的子类。
定制打印显示
class MyBad(Exception):pass
try:
raise MyBad('SORRY!')
except MyBad as X:
print(X)
class MyBad(Exception):
def __str__(self):
return 'Always look on the bright side of life...'
try:
raise MyBad()
except MyBad as X:
print(X)
注:py3.0中,异常必须由类定义(引发并捕获一个类实例对象)。异常类必须派生自内置类BaseException(或子类Exception,以支持常规类型的异常的全捕获)
异常的设计
1.try语句可以嵌套
python会挑选并执行具有相符except、最近的try。
2.所有的错误是异常,所有的异常并非都是错误。
3.异常提供一种方式来传达结果信号,而不适用返回值。
4.sys.exc_info通常允许一个异常处理器获取对最近引发的异常的访问。
如果没有处理器正在处理,返回包含了三个None值的元组。否则,将会返回(type、value和traceback):type是正在处理的异常的异常类型。value是引发的异常类实例。traceback是一个traceback对象,代表异常最初发生时所调用的堆栈。
它记录每个线程的异常信息,因此是线程专有的方式。
5.内存错误、一般程序错误、迭代停止、键盘中断以及系统退出,等等,都会引发异常。这类异常通常是不应该拦截的。
python也提供内置sys.exit(statuscode)调用来提前终止。
6.空except和捕获Exception类也会捕捉一般程序设计错误,但这类错误多数时候都应让其通过。
7.PyDoc为模块和对象提供了一个文档系统,并整合了python的文档字符串功能。
8.PyChecker和PyLint系统可以在脚本运行前把大量的常见错误预先缓存起来。
9.PyUnit(在库手册中称为unittest),提供了一个面向对象的类框架,来定义和定制测试案例以及预期的结果。
10.doctest标准库模块,提供第二个并且更为简单的做法来进行回归测试。
11.为了真正把代码中的性能瓶颈隔离出来,需要通过time或timeit模块内的时钟工具新增计时逻辑,或者在profile模块下运行代码。
profile是标准库模块,为python实现源代码配置工具。
12.在默认情况下,它会打印报告到标准输出流,从而给出性能的统计结果:每个函数的调用次数、每个函数所花时间等
13.python标准库包含了一个命令行源代码调试器模块,称为pdb
14.Psyco系统提供了实时编译器,可以把python字节码翻译成二进制机码,而Shedskin提供了Python对C++的翻译器。
15..pyo优化后的字节码文件,这是以-O Python命令标志位运行所产生的文件,这只提供了有限的性能提升,并不常用。
16.str.encode()和bytes(S,encoding)把一个字符串转换为其rawbytes形式。
17.bytes.decode()和str(B,encoding)把raw bytes 转换为其字符串形式。