- 错误和异常
异常:程序出现了错误而在正常控制流以外采取的行为。
跟踪记录(traceback):包括错误名称、原因和发生错误的行号。
- 检查和处理异常:
异常可以通过try语句来检查,任何在try语句块里的代码都会被监控,检查有无异常发生。
Try另种形式:这两语句是互斥的
try-except:一个try语句中对应一个或多个except
Try-findally:只能有一个finally或是try-except-finally复合语句
语法格式:
Try:
Try_suite #监控这里的异常
Except Exception[,reason]:
Except_suite #异常处理代码
try语句让出错代码不至于影响整个程序的运行,而是之间输出错误原因而继续进下一步操作。注意的点,在try语句中出错代码之后的代码不在运行
如果try语句的代码完成后没有异常发生,就会忽略掉except语句继续执行,而如果发生了异常,except语句保存错误的原因,控制流立即跳转到对应的处理器,显示出一个包含错误原因的错误信息,而整个程序不会被中断
- *****核心笔记:忽略代码,继续执行,和向上移交
try语句中异常发生点后的剩余语句永远不会执行。一旦一个异常被引发,就必须决定控制流下一步到达的位置。解释器将搜索处理器,一旦找到,就开始执行处理器中的代码
如果找不到合适的处理器,异常就一直往上移交给调用者去处理,直到找到合适的处理器,如果到达最顶层都没有找到相应的处理器,那么这个异常就是未处理的,显示出跟踪记录和异常后,程序退出运行
- 包装和内建函数
>>> float('foo')
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
float('foo')
ValueError: could not convert string to float: 'foo'
>>> float([1,2])
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
float([1,2])
TypeError: float() argument must be a string or a number, not 'list'
Float有两种错误:
- 输入类型不正确(只能识别字符串和数字)TypeError
- 值不正确(不能转换相应的浮点模式)ValueError
想要安全的调用float函数,就要把float函数放到try语句中,使异常发生但是不会终止整个程序
>>> try:
float('foo')
except Exception as e:
print(e)
could not convert string to float: 'foo'
- 带有多个excep的try语句
把多个except语句连接在一起,处理一个try块中可能发生的多种异常。
语法格式:
Try:
Try_suite #监控这里的异常
Except Exception[,reason1]:
Except_suite #异常处理代码
Except Exception[,reason2]:
Except_suite #异常处理代码
执行顺序:
先尝试执行try子句:
- 如没有异常,忽略所有的except从句继续执行。
- 如有异常,解析器将在这个except中找到匹配的异常,如果找到对应的异常处理器,执行流将跳转到这里。
def safe_float(obj):
try:
retval = float(obj)
except ValueError:
retval = 'could not convert non-number to float'
except TypeError:
retval = 'object type cannot be converted to float'
return retval
print(safe_float('xyz'))
print(safe_float(()))
执行结果:
could not convert non-number to float
object type cannot be converted to float
- 处理多个异常的excep语句
在一个except子句里处理多个异常。Except语句在处理多个异常时要求异常被放在一个元组中:
语法格式:
Try:
Try_suite #监控这里的异常
Except (Exception1,1Exception2) [,reason]:
suite _for_exceptions_Exc1_to_ExcN
示例:
如果由于其他原因,也许是内存规定或是设计方面的因素,要求函数中的所有异常必须使用同样的代码处理,可以这样满足需求:
def safe_float(obj):
try:
retval = float(obj)
except (ValueError,TypeError):
retval = 'argument must be a number or numeric string'
return retval
print(safe_float('xyz'))
print(safe_float(()))
执行结果:
argument must be a number or numeric string
argument must be a number or numeric string
- 捕获所有异常
可以使用exception捕获异常
语法格式:
Try:
Try_suite #监控这里的异常
Except Exception , e:
#handle real errors
或者:
Try:
Try_suite #监控这里的异常
Except BaseException , e: #捕获所有异常
#handle all errors
核心风格:不要处理并忽略所有错误,错误无法避免,try-except的作用是提供一个可以提示错误或处理错误的机制,而不是一个错误过滤器,使用Exception会忽略很多的错误,这样的用法是缺乏工程实践的表现,不赞同这种做法。也不能把大段的代码放到try语句中,只有一小部分可能会引起异常的部分使用try语句,使之不会干扰程序的正常运行
- “异常参数”
异常也可以有参数,异常引发后它会被传递给异常处理器。参数是作为附加的帮助信息传递给异常处理器的。
try:
float(['fpp'])
except TypeError, diag:
pass
print type(diag)
print diag
<type 'exceptions.TypeError'>
float() argument must be a string or a number
在except中的diag就是异常参数
核心风格:遵循异常参数规范
如果引发一个ValueError,那么最后提供和解释器引发ValueError时一致的参数信息,可以保证代码的一致性,也能避免其他应用程序在使用这个模块的时候发生错误
- 在应用使用我们封装的函数
#coding:utf-8
#定义safe_float函数
def safe_float(obj):
try:
retval = float(obj)
except (ValueError, TypeError) :
retval = 'abcdefg'
return retval
#定义主函数
def main():
#打开名为cardlog的文本文件,并传给log
log = open(r'C:\python\tst\cardlog.txt', 'w')
#try-except语句验证carddata文件是否存在
try:
#打开carddata文本文件,传给ccfile
ccfile = open(r'C:\python\tst\carddata.txt', 'r')
except IOError as e:
log.write('no txns this month\n')
log.close()
return
#将ccfile中的文字读出传给txns
txns = ccfile.readlines()
ccfile.close()
total = 0.00
log.write('account log:\n')
#for循环遍历txns
for eachTxn in txns:
#将txns中每行文字进行float变换
result = safe_float(eachTxn)
#使用isinstance函数判断result里的值是否为浮点数
if isinstance(result, float):
#计算浮点数的总和
total += result
log.write('data... processed\n')
else:
log.write('ignored: %s' % result)
#输出总的浮点值
print('$%.2f (new balance)' % total)
log.close()
if __name__ == '__main__':
main()
信用卡交易系统,用来统计余额
- else子句
在try范围中没有异常被检测到时,执行else子句。
在else范围中的任何代码运行前,try范围中的所有代码必须完全成功。
- Finally
Finally子句是无论异常是否发生,是否捕获都会执行的一段代码
语法格式:
Try:
A
Except MyException:
B
Else:
C
Finally:
D
- try-finally语句
另一种使用finally的方式是finally单独和try连用。try-finally不是用来捕捉异常,作为替代,它常常用来维持一致的行为,而无论异常是否发生。
语法格式:
Try:
Try_suite
Finally:
Finally_suite #无论如何都执行
示例:
try:
#打开carddata文本文件,传给ccfile
ccfile = open(r'C:\python\tst\carddata.txt', 'r')
except IOError as e:
log.write('no txns this month\n')
finally:
ccfile.close() #无论是否有异常文件都会被关闭
本质:可以同时处理在原始的try语句块和finally语句块中发生的错误。这种方法问题:当finally语句块中地区发生异常时,会对手原来异常的上下文信息,除非在某个地方保存了它。
烦的这种写法的理由:在很多情况下,异常处理器需要做一些扫尾工作,而如果你在异常处理之前,用finally语句块中是否了某些资源,你就不能再去做这些工作了,简单的说:finally语句块并不是如你所想的是“最终的final”
注意点:如果finally中的代码引发了另一个异常或由于return、break、continue语法而终止,原来的异常将丢失而且无法重现引发。
- try-except-else-finally
无论选择什么语法,至少要有一个except自己,而else和finally都是可选的