如何用Python上下文管理器批量处理连续多个ModuleNotFoundError
处理连续ModuleNotFoundError的上下文管理器实现
需求是实现一个上下文管理器,能在一次with块中连续捕获并处理任意数量的ModuleNotFoundError,让下面的代码对每个不存在的模块都执行自定义处理逻辑:
with handle_ModuleNotFoundErrors(): import this_is_not_installed import neither_is_this import none_of_these_are_installed
现有代码的问题
当前实现只能处理第一个ModuleNotFoundError,后续异常不会被捕获:
from contextlib import contextmanager import re @contextmanager def handle_ModuleNotFoundErrors(): try: yield except ModuleNotFoundError as e: failed_module = re.search(r"'((?:\'|[^'])+)'", e.msg).group(1) print(f'Handling {failed_module}...') with handle_ModuleNotFoundErrors(): import asdfasdf1 import asdfasdf2 import asdfasdf3 # 输出仅为:Handling asdfasdf1...
这是因为yield只会执行一次,第一个异常抛出后,上下文管理器的except块处理完就退出了,剩下的导入代码根本没机会执行。
解决方案:循环执行yield以捕获连续异常
要实现连续捕获,需要在上下文管理器中用循环包裹try-yield逻辑,每次捕获异常处理后,让代码继续执行后续的导入操作:
from contextlib import contextmanager import re @contextmanager def handle_ModuleNotFoundErrors(): while True: try: yield break # 如果没有异常,正常退出循环 except ModuleNotFoundError as e: failed_module = re.search(r"'((?:\'|[^'])+)'", e.msg).group(1) print(f'Handling {failed_module}...') # 处理完异常后,循环会再次执行yield,让后续代码继续运行 with handle_ModuleNotFoundErrors(): import asdfasdf1 import asdfasdf2 import asdfasdf3
输出结果
Handling asdfasdf1... Handling asdfasdf2... Handling asdfasdf3...
原理说明
- 第一次
yield时,执行import asdfasdf1,抛出异常,进入except块处理,完成后回到循环开头。 - 第二次
yield时,跳过已经失败的import asdfasdf1,继续执行import asdfasdf2,再次捕获异常处理。 - 第三次
yield执行import asdfasdf3,捕获处理异常。 - 当所有导入都执行完(或遇到非
ModuleNotFoundError的异常时),如果没有异常,yield后执行break退出循环;如果是其他异常,会直接向上抛出,不会被当前上下文管理器处理。
内容的提问来源于stack exchange,提问作者reynoldsnlp
相关产品推荐
相关产品推荐

