python中的异常


python中的异常(exception)是一种类(在老版本里,同时也可以是一个字符串)。定义异常同定义类是相同的。Exception类应该作为所有异常类的基类,其他的类都由这个类派生出来,不论是内建的异常还是自定义的异常。同不同类的继承一样,在自定义的异常中的__init__(self,[option])中写上Exception.__init__(self,[option])是一个好习惯。

当有一个异常发生时(不论是解释器发出的异常还是通过raise发出的异常),异常的3个信息将会被记录下来。这3个信息是异常的类型,值和调用点。对于基于类的异常而言,一般类型是类名(或基类名),值是类的实例。这样的设计决定了raise的语法。

raise有3个可选参数。如果没有参数raise生成当前活动的异常。如果第一个参数是实例,则异常的类型就是实例的类,值是实例本省,并且第二个参数必须为空。如果第一个参数是类,则如果第二个参数是类的实例,这个实例就是异常的值,如果是一个tuple,异常的值就是以这个tuple初始化的类的实例。如果raise有第三个参数,这个参数就是一个traceback实例。下面是语法:
raise_stmt ::= "raise" [expression ["," expression ["," expression]]]
常用的形式是raise MyError(arg1, arg2, ...)

同样,异常的结构也决定了except的使用方法。except如果没有参数,则是一个默认处理器,这种方式需要谨慎使用。第一个参数可以是类名或是由多个类名组成的tuple。在','之后可以是第二个参数。是这种异常的一个实例,异常的参数储存在这个参数的.args中。可以使用__getitem__和__str__来使的参数的传递可以直接进行。因为.args是基类Exception的一个属性,所以使用__getitem__的方法传递参数更合理一些。

如果使用finally,则不能使用except。当使用finally时,如果没有异常发生,则finally中的语句被执行;如果有异常发生,则异常被保存(意味着在finally中不能得到异常的信息),执行finally语句,完成之后在继续传递异常。如果在finally中有return,break,raise,则旧的异常丢失。

特别的在except之后还可以有else:语句。这些语句是在try语句都执行完之后执行的。
下面是语法:
try_stmt ::= try_exc_stmt | try_fin_stmt
try_exc_stmt ::= "try" ":" suite
  ("except" [expression ["," target]] ":" suite)+
  ["else" ":" suite]
try_fin_stmt ::= "try" ":" suite "finally" ":" suite
代码中常常见到的形式是:
class MyError(Exception):
    def __init__(self):
        Exception.__init__(self)
    def __str__(self):
        return "MyError"
    def __getitem__(self, key):
        if key == 0:
            return 0
        else:
            raise IndexError

try:
    raise MyError
except MyError, (x):
    do_clearn(x)  #这里的x为0
    raise
或者使用finally来代替except。