Python的异常处理语句try...except大家都很熟悉了,例如:
try:
1/0
except(Exception) as ex:
print(ex)
integer division or modulo by zero
但是如果try逻辑比较复杂,或者有大段的except处理语句,这种方式写的代码就显得比较臃肿,让人看起来比较头疼。
这时候可以考虑将try...except语句和被检测逻辑代码拆分解耦,采用的就是with语句。
with语句的执行原理这里就不多说了,网上很多参考资料,这里主要关注使用with语句。
首先利用contextlib.contextmanager定义一个上下文管理器:
@contextlib.contextmanager
def context_manager():
try:
yield
except (Exception) as ex:
print(ex)
如上,在该管理器中实现了try...except逻辑。
然后通过with语句编写被检测逻辑:
with context_manager():
1/0
integer division or modulo by zero
可以看到,结果与直接使用try...except逻辑一致。
通过此方法将被检测逻辑与异常处理逻辑进行了拆分解耦。
如果异常处理逻辑比较复杂,或者是有多处代码使用了相同的异常处理逻辑,采用这种方式就会体现出优势。
下面根据前面的例子,分析一下这种方式进行异常处理的执行流程。
- 进入with语句时,会先执行到context_manager的yield语句;
- 然后就结束了在context_manager的执行,开始执行with语句后包含的逻辑(如上的1/0);
- 包含逻辑执行结束时(无论是正常结束还是抛出异常),执行流程都会返回到context_manager,接着yield语句后继续执行;
- 于是在后续的except语句中捕获了异常。