异常在程序中的作用
- Error Handling:能够在异常处理语句中捕获并响应错误信息
- Event Notification:即当我们应用程序在传入数据并进行数据处理过程中,针对不合法的事件我们是采取抛出异常而不是返回一个表示不合法的数据结果
- Special-case handling:在异常处理器处理程序个别极端情况,可以通过assert来检查条件是否如我们的预期值一样
- Termination actions:即保证程序中的资源能够在异常发生之后正常关闭
- Unusual control flows:不正常的控制流,使用raise抛出异常信息
异常处理机制
默认异常处理器,即由python自动搜索匹配对应的异常信息
1 | 复制代码`# python命令行,默认是3.6,以下没有特殊说明全部是基于这个版本>>> str="keithl">>> str[10]` |
捕获异常信息
1 | 复制代码`# exception.pydef catch_index():` |
抛出异常,使用raise
1 | 复制代码`# exception.pydef raise_index():` |
自定义异常
1 | 复制代码`# exception.pyclass MyException(Exception):` |
使用finally终止try语句
1 | 复制代码`# exception.pydef raise_index_finally():` |
异常语句
try/except/else语句
- 语句块的定义
1 | 复制代码`try:` |
- try/except/else工作原理
- 当在try语句块中发生异常时,异常类型将会匹配except对应的name,然后根据对应的name分配对应的异常类对象,执行statement中的语句
- 当在try语句块中发生异常但没有在except中匹配到对应的name,python将会查询其他的异常直至进程最高级别的异常并退出程序,打印出默认的异常信息
- 如果try语句正常执行,那么最后也将会执行else语句
- 捕获任意或所有异常
- 使用
except:
,即后面没有携带任何异常类,将会捕获先前没有定义的异常类 - 使用
except (e1,e2,..)
,即只要业务代码中抛出的异常是在定义的一系列异常列表中(e1,e2,..),那么就会在except语句中被捕获处理
except:
与except Exception:
except:
是捕获所有的异常,但存在不足,一是捕获和业务代码无关的系统错误,二是会拦截其他程序的异常处理except Exception:
:py3.x建议使用这个Exception类,同时可以避免上述问题,Exception会忽略与系统操作相关的异常,如系统退出py时报出的异常
1 | 复制代码`# exception.py# `except:`执行遇到系统退出的时候会捕获异常def test_exception():` |
1 | 复制代码`# `except Exception:`在系统退出的时候没有捕获异常def test_exception():` |
- py2.x与py3.x的异常语句作用域
- py2.x可以支持
except Exception as e
以及except Exception,e
,py3.x仅支持except Exception as e
- py2.x的异常语句Exception对应的实例变量e是全局变量,在try语句块外还可以直接访问
- py3.x的异常语句Exception对应的实例变量e是局部变量,在try语句块外不能访问,但是可以保存在一个全局的变量中
try/finally语句
- 语句块定义
1 | 复制代码`try:` |
- try/finally工作原理
- 当try语句块中的业务逻辑是正常执行的时候,在程序退出返回的时候将会执行finally语句块
- 当try语句块中的业务逻辑出现异常的时候,仍然会执行finally语句块并将异常信息一并向顶层程序抛出
- 示例
1 | 复制代码`# exception.pydef raise_exception():` |
try/except/finally语句
- 这个在上面的基础上添加一个异常处理块,其一般模板为
1 | 复制代码`try:` |
raise语句
- raise instance:raise 语句抛出一个异常信息类型图13
- raise class:raise 语句创建一个异常类class的实例并抛出异常信息图14
- raise:将一个异常类class信息抛出并往顶层程序传播
- 在一个try语句中发生的异常信息类会在except语句中按照顺序进行匹配
- 抛出的异常类是except定义的异常类的子类或本类,其他在except定义的异常类将不捕获异常
- 抛出的异常类如果是except定义的异常类的父类,也不会捕获到该父类的异常
- 仅py3.x支持的from语句
raise newException from otherException
assert语句
- 语法:
assert test,data # data是可选的
- 工作原理如下:
1 | 复制代码if __debug__: if not test: raise AssertionError(data) |
- 示例:
with/as上下文管理器
- 基本语法
1 | 复制代码with expression [as variable] with-block# 表达式expression返回的是一个实现上下文管理器协议的对象 |
- 场景一:IO操作自动打开和关闭资源
1 | 复制代码`# 打开文件filepath并且自动读取with open("filepath") as file_object: for line in file_object:` |
- 场景二:应用在线程锁中,自动获取和释放锁
1 | 复制代码`# 在一个线程中对语句块进行锁操作lock = threading.Lock() # 导入threading模块with lock: # 在业务代码执行之前自动获取锁,在执行完成之后自动释放锁,除非有异常抛出` |
- 场景三:在decimal模块中使用上下文管理来设置decimal操作业务数据的格式,退出后格式自动清除失效
1 | 复制代码`import decimalwith decimal.localcontext() as ctx:` |
- with表达式语句的工作原理
- 上下文管理器对象必须有实现内置操作符
__enter__
和__exit__
方法 - 在with语句中返回一个对象管理器并分配一个变量的时候将会回调
__enter__
方法 - 执行嵌套的语句块,也就是上面的相关业务代码
- 当有异常信息抛出的时候,就会回调
__exit__
的方法,同时携带type,value,traceback三个参数(通过sys.exc_info获取到) - 正常执行完成之后,也会回调
__exit__
的方法
1 | 复制代码`# exception.pyclass WithContextObject:` |
- 使用多个with上下文管理器
1 | 复制代码`# 基本语法with open(file_path1) as reader,with open(file_path2) as writer: for line in reader:` |
本文转载自: 掘金