一、异常
异常就是在触发异常条件时(解释器或程序员)而采取相应的措施
c++中异常使用try, throw, catch等关键字,而python中使用try, raise, except等
二、标准异常
1、综述:
python异常都是类,其中BaseException是所有异常的根基类
Exception, SystemExit, GeneratorExit, KeyboardInterrupt是直接有BaseEXception派生的
其他异常类都是直接或间由Exception派生
2、派生图:
3、标准异常(根据python核心编程外加python3源代码进行扩充修改):
三、检测与处理异常
1、try-except:
a.一个except:
try: 被检测的部分 except 异常类型: 异常处理部分
当被检测的部分出现指定的异常类型时,会执行异常处理部分;
没有出现指定异常时,忽略except中的语句
例子:
1 try: 2 f = open('test.txt') 3 except FileNotFoundError: 4 print('This file is not exist!') 5 # 当不存在该文件时,输出指定语句 6 # 当文件存在时,则没有影响
也可以对特定的异常进行忽略处理:
try: 被检测的部分 except 异常类型: pass
这样当出现特定异常时,可以忽略处理:
1 try: 2 f = open('test.txt') 3 except FileNotFoundError: 4 pass 5 6 # 这样,当文件不存在时,会忽略而继续运行程序
b.异常参数:
可以在异常部分后面加上:as 参数名
则可以通过该参数来保留错误的原因
例子:
1 try: 2 f = open('test.txt') 3 except FileNotFoundError as e: 4 print(str(e)) 5 print(e.args) 6 7 '''输出: 8 [Errno 2] No such file or directory: 'test1.txt' 9 (2, 'No such file or directory') 10 ''' 11 12 # e为异常参数,保留了异常错误的原因 13 # e为一个错误编号和一个错误原因的字符串组成的tuple
c.多个except语句
try: 被监测部分 except 异常类型1: 处理1 except 异常类型2: 处理2 ...
当被检测部分出现异常时,执行相应的异常处理部分
其余的except不会执行
例子:
1 exp = input('Please input the math expression:') 2 try: 3 print(eval(exp)) 4 except ZeroDivisionError as e: 5 print("0 can't be / or %") 6 except TypeError as e: 7 print(e) 8 9 ''' 10 输入:3 % 0 11 输出:0 can't be / or % 12 输入:3 & 1.5 13 输出:unsupported operand type(s) for &: 'int' and 'float' 14 '''
d.多个异常类型:
try: 被检测部分 except (异常类型1, 异常类型2, ...): 异常处理部分 ...
多种异常类型进行同种处理
e.捕获所有异常:
由于Exception是所有异常的基类(除几个特殊的)
所有可以直接用Exception作为异常类型:
try: 被检测部分 except Exception: 处理 ...
当然,如果连解释器的错误和用户强行中断也要捕获,可以用BaseException作为异常类型
注意,在捕获所有异常时,最好采取行动而不是pass掉,
一般只有对特定的异常才会采取忽略处理
例子:
f.综合实例(摘自《core python programming》):
1 def safe_float(obj): 2 """safe version of float(obj)""" 3 try: 4 retval = float(obj) 5 except (ValueError, TypeError) as diag: 6 # ValueError: 当传入str等 7 # TypeError: 当传入{},()等 8 retval = str(diag) 9 return retval 10 11 12 def main(): 13 """handles all the data processing""" 14 log = open('cardlog.txt', 'w') 15 # 用来保留日志的文件 16 try: 17 ccfile = open('carddata.txt', 'r') 18 except IOError: 19 log.write('no txns this month ') 20 log.close() 21 return 22 23 txns = ccfile.readlines() 24 ccfile.close() 25 total = 0.0 26 log.write('account log: ') 27 28 for eachTxn in txns: 29 result = safe_float(eachTxn) 30 if isinstance(result, float): 31 total += result 32 log.write('data... processed ') 33 else: 34 log.write('ignored: %s' % result) 35 # 忽略字符串,只对float处理 36 print('$%.2f (new balance)' % total) 37 log.close() 38 39 40 if __name__ == '__main__': 41 main()
2、else语句:在try范围内没有异常被检测到时,执行此语句代码
try: 被监测部分 except 异常1: 处理1 except 异常2: 处理2 ... else: 处理
只有当异常1,异常2,... 都未被检测到时,才会执行else后面语句
例子:
3、finally语句:无论异常是否发生,都会执行该语句下的代码
a.try-except-finally:
try: 被检测部分 except 异常: 处理 ... finally: 语句块
finally下的语句块最终都会执行
当try范围内产生一个异常时,会立即跳转到finally语句
当finally语句执行完成后,继续向上一层引发异常
但是,如果finally中的代码发生异常或由于return, break, continue等终止时,则不会引发原异常
例子:
b.try-finally:
此处并没有except语句,所有目的并非是处理异常,
通过该模式是为了维持代码的执行,而不管异常发生与否
例子(信用卡例子关闭文件):
四、触发异常
可以通过raise语句来人为的引发异常(类似于c++中的throw)
raise someException, args, traceback
应用:
1 # 只允许输入q或enter 2 try: 3 choice = input('Please input [enter] 4 to continue or [q] to quit:') 5 if choise not in ('q', ' '): 6 raise IOError 7 except IOError: 8 print('Just can input [enter] or [q]')
五、断言
用于测试一个表达式,如果返回值为假则触发异常
try: assert 表达式 except AssertionError: 处理
当表达式为假时,将会执行处理部分
用在产品发布之前,对程序的逻辑、文档、约定等进行检查
在生产环境时应去除断言
例子:
1 try: 2 choice = input('Please input [enter] 3 to continue or [q] to quit:') 4 assert choise in ('q', ' '), ' 5 ...