什么是异常?
因为程序出现了错误而在正常流程控制以外采取的行动。这个行动分为两个阶段:首先是引起异常发生的错误;其次是检测(和可能采取的措施)阶段。
如:NameError
print ab
那对于异常如何检测和处理呢?
异常可以用 try 语句来检测。任何在 try 语句块中的代码都会被监测,检查有误异常发生。
try 语句主要有两种主要形式:try-except 和 try-finally ,这个两个语句是互斥的,只能使用其中一个。一个 try 可以对应一个或者多个 except 子句,但是只能对应一个 finally 子句,或者是一个 try-except-finally符合语句
try:
try_suite #监控这里的异常
except Exception[,reason]:
except_suite #异常处理代码
try:
f = open('absd','r')
except IOError,e:
print "could not open file:",e
当发生IOError异常时,这里打印出一条诊断消息,但程序仍然继续执行。当程序运行时,解释器尝试执行 try 块里面的代码,如果代码完成后,没有异常发生,执行流会忽略 except 语句继续执行,这里保存了异常的原因放置在e中。
也可以带有多个except的try语句
try:
try_suite #监控这里的异常
except Exception1[,reason1]:
except_suite1 #异常处理代码
except Exception2[,reason2]:
except_suite2 #异常处理代码
这里顶一个以safe_float函数,float内建函数将把任意一个数值类型转换成浮点型,同时也能把字符串表示的数值转成浮点型,但对于其它类型就无能为力。
def safe_float(obj):
try:
retval = float(obj)
except ValueError:
retval = "could not convert non-number to float"
except TypeError:
retval = "object type can not be converted to float"
return retval
print safe_float('xyz')
print safe_float(200L)
此外对于处理多个异常的except语句,也可以在一个except子句中处理多个异常。except语句在处理多个异常时要求被放置在一个元组里面。
try:
try_suite #监控这里的异常
except (Exception1[,Exception2[,...])[,reason1]:
except_suite1 #异常处理代码
异常被引发后,异常参数reason是作为附加帮助信息传递给异常处理器,将会是一个包含来自导致异常的代码的诊断信息的类实例。
def safe_float(obj):
try:
retval = float(obj)
except (ValueError,TypeError):
retval = "argument must be a number or numertic string"
return retval
print safe_float('xyz')
print safe_float(200L)
由于多数内见异常是从StanardError派生的,和这个元组只包含了一个只是错误原因的字符串,而调用str(reason)可以得到一个可读性较好的字符串,因此做如下修改。
def safe_float(obj):
try:
retval = float(obj)
except (ValueError,TypeError),args:
retval = str(args)
return retval
print safe_float('xyz')
print safe_float([])
这里给出一个读取文件的针对异常处理的经典方式
try:
try:
cfile = open("test,txt",'r')
tx = cfile.readlines()
except IOError:
log.write("no tx this month\n")
finally:
cfile.close()
代码片会尝试打开并且读取数据,如果在某一步发生了错误,会写入到日志,随后文件被正确关闭。
此外还有一个with语句,该语句的目的杂鱼从流程图中把try,except,finally关键字和资源分配释放相关代码统统去掉。
with context_expr [as var]:
with_suite
注意with仅能巩固支持上下文管理协议的对象,而file是可以,其他的这里先不介绍
with open("/etc/passwd",'r') as f:
for eachline in f:
pass
如果一切正常,把文件对象赋值给f,然后是迭代器遍历文件中的每一行,当完成时,关闭文件,无论在这一段代码的开始,中间,还是结束时发生异常,会执行清理的代码,此外文件仍会被自动关闭。