完整的异常处理流程
try … except … else … finally … [raise]
try后接except或finally,except可以有多个,finally只有一个
代码块 | 作用 | 备注 |
---|---|---|
try | 业务代码 | try块应尽量简单,以便出现异常时快速定位到具体的行 |
except | 捕获异常 | 先处理小异常(子类),后处理大异常(父类) |
else | 向外传播 | try块无异常时,else块的代码放在try块下也一样 |
finally | 回收资源 | 回收try块打开的物理资源,如数据库连接、网络连接 |
raise | 自行引发异常 | if …: raise |
except
try块的业务代码异常时,跳转except块,对异常进行处理,避免程序报错并中断
捕获多个异常:写成元组即可,如:except (异常类1,异常类2,…): pass
捕获所有异常:不指定异常类,如:except: pass
输出异常信息:except Exception as e: print(e.args)
异常类对象的属性 | errno | strerror | args | with_traceback() |
---|---|---|---|---|
包含的信息 | 编号 | 描述 | 编号 + 描述 | 传播轨迹 |
系统内置的异常类
自定义的异常类通常继承Exception类或其子类
BaseException | Exception | ArithmeticError | ZeroDivisionError |
---|---|---|---|
FloatingPointError | |||
OverflowError | |||
LookupError | IndexError | ||
KeyError | |||
BufferError | |||
GeneratorExit | |||
KeyboardInterrupt | |||
SystemExit |
finally
总是会执行,无论其它代码块中是否有return或异常。块中可以包含完整的异常处理流程
例外:如果在except块中用os._exit(1)退出了python解释器,finally块不会执行
由于finally块总是会执行,finally下的return或raise会使其它代码块中的return或raise失效
raise
- 单独的raise——默认引发RuntimeError
- raise + 异常类
- raise + 异常对象
在except块中使用raise
except捕获系统异常,记录在日志中;raise引发自定义异常,反馈给用户
except Exception as e: raise AuctionException(e)
把原始异常Exception包装成AuctionException
在except块中的raise若不带参数,会引发整个except块的异常
# 异常传播轨迹
import traceback
try:
pass
except:
traceback.print_exc()
format_exc()
print_exc的完整形式:print_exception(etype, value, tb, limit, file)
参数 | etype | value | tb | limit | file |
---|---|---|---|---|---|
指定内容 | 异常类型 | 异常值 | traceback信息 | 传播层数 | 输出位置 |
未指定file时,输出到屏幕
异常处理规则
不要过度使用
对外部不可预知的错误才使用异常;对已知的、普通的错误,要编写处理代码
对异常的处理方式
- 修复
- 返回其它值
- 提示用户重新操作
- 传给上层调用者处理