python提供了异常处理机制。在默认情况下,如果程序中出现异常,python会打印出错消息,这是python默认的异常处理器。除此之外,python还允许用户自行捕获并按自己的需求处理异常。本文将从异常数据类型、异常触发方式、异常的捕获及处理三个方面进行介绍。
异常类型
异常是通过类实现的。
内置异常类型
BaseException
Exception
是所有其他内置异常的超类,除了系统退出事件类之外,比如SystemExit, KeyboardInterrupt, GeneratorExit。ArithmeticError
所有数值错误的超类。
用户自定义异常类
一般需要继承自BaseException或者Exception:
class MyException(BaseException):pass
异常打印:
传递给异常类构造函数的所有参数都会保存在args元组中,并且在打印该实例的时候自动显示,另外在由默认异常处理器处理异常时,该数据也会作为消息的一部分:
>>> I = IndexError('datadata')
>>> I.args
('datadata',)
>>> print I
datadata
>>> raise IndexError('datadatadata', 'hhhhhh')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: ('datadatadata', 'hhhhhh')
异常虽然不是字符串对象,但在打印的时候会调用str运算符重载协议来打印成字符串;通过修改str可以定制打印:
class MyBad(Exception):
def __str__(self):
return 'string wanted to print'
这样在异常实例被打印或者异常到达默认处理器时,会打印__str__方法返回的字符串。
为异常提供数据和方法
可以通过定制的构造函数为异常实例提供额外的数据属性,还可以增加额外的函数:
class MyException(Exception):
logfile = '**.txt'
def __init__(self, line, file):
self.line = line
self.file = file
def logerr(self):
log = open(self.logfile, 'a')
print >> log 'error at', self.file, self.line
可以通过异常对象调用这些额外的数据属性值或者方法。
异常触发方式
自动触发
由程序自动触发。
手动触发
- raise语句
raise Exception #隐式调用构造函数
raise Exception() #显式调用构造函数
raise Exception(args) #通过传递参数显式调用构造函数
raise #触发最近的异常,常用于异常处理器中,以传播已捕获的异常
raise触发的异常必须是类的一个实例。raise语句会把异常类型和实例一起发送,except exception as data
语句和这一概念相关,data会引用raise传递的实例对象。
- assert语句
assert语句可以看成是含有if判断的raise语句的替代物:
assert expression , data#data是可选的,在异常没有被捕捉到时,data会做为出错消息的一部分
if not expression:
raise exception
异常处理
默认处理器
当有异常被触发,而没有try语句捕获时,会调用python的默认异常处理器:打印标准出错消息。消息包含了个堆栈跟踪Traceback以及异常的名称和细节。
try处理器
try语句的语法:
try:
程序
except exception1:
...
except (exception1, exception2):
...
except exception as data:#捕获的exception类型的异常实例赋值给data,这样可以使用异常实例的属性
...
except: #所有其他类型的异常
...
else:
...
finally:
...
try语句必须有一个except或者finally;可以有多个except子句;如果有else,那么必须至少有一个except;可以只有finally。
try语句是可以嵌套的。
excep:...
子句会引发一些问题:也会捕捉到系统退出、内存耗尽、键盘中断等异常,但是实际上我们会希望忽略这些异常。
except Exception:...
可以用来解决这一问题。
try/except/else
try:
fun()
except MyException:
print "error"
else:
print "no error"
在上面的代码中,在执行try中的主要程序时:
触发异常,首先捕捉该异常
如果有匹配项(异常是某个exception或者是其子类),表示该异常被try/except**捕捉**到,那么执行该匹配except分支中的语句,并从异常中恢复,此时异常die;否则,表示该异常没有被try语句捕捉到,那么把异常向上层传递,比如这里会把异常传给python的默认异常处理器,打印出错消息,并且终止程序。没有触发异常,那么会执行else语句。
try/finally
try:
fun()
finally:
close
上面的代码中,无论主代码中的程序是否出现异常,finally语句总会被执行。区别在于:当出现异常时,finally语句执行后,把异常向上传递到外层try或者默认异常处理器,打印出错消息并退出;没有出现异常时,finally语句执行后,接着执行try/finally语句后面的代码。
try/finally一般用来确保关闭文件、终止服务器的连接调用等。
with/as是try/finally的一个替代方案,通过运行对象的环境管理逻辑来确保终止行为的发生。
异常不仅仅是错误
异常除了错误处理,还可以用到很多地方。
事件通知
终止行为
其他
sys.exc_info()
返回:
三元组(type, value, traceback):type是异常类型;value是异常实例;traceback代表异常最初发生时所调用的堆栈
当使用空的except子句时,无法确定捕捉的异常到底是什么类型的,这时可以通过sys.exc_info来确定:
try:
...
except:
sys.exc_info()