整体说明
contextlib模块是 Python 标准库的一部分,提供了一系列简化上下文管理器实现的实用工具
@contextmanager 装饰器
@contextmanager允许将生成器函数转换为上下文管理器,无需显式定义类@contextmanager核心逻辑通过yield分割为“进入上下文”和“退出上下文”两部分示例:
1
2
3
4
5
6
7
8
9
10from contextlib import contextmanager
def file_manager(file_path, mode):
file = open(file_path, mode)
yield file
file.close()
with file_manager('test.txt', 'w') as f:
f.write('Hello, contextlib!')- 在这个例子中,
yield之前的代码file = open(file_path, mode)用于获取资源,yield之后的代码file.close()用于释放资源 - 注:
yield之后的语句在第二次调用函数时被调用(第一次调用函数返回yield的结果)
- 在这个例子中,
closing类
对于只提供
close()方法但未实现上下文协议的对象,closing可确保其close()被调用1
2
3
4
5from contextlib import closing
import urllib.request
with closing(urllib.request.urlopen('https://www.example.com')) as response:
html = response.read()- 上述代码等价于手动使用
try-finally块来调用close()方法,但closing类使代码更加简洁
- 上述代码等价于手动使用
suppress上下文管理器
在需要忽略某些非关键异常时,
suppress可替代繁琐的try-except1
2
3
4
5
6from contextlib import suppress
with suppress(FileNotFoundError):
with open('nonexistent_file.txt', 'r') as f:
content = f.read()
print("程序继续执行,不抛出异常")suppress还可以同时抑制多个异常,如with suppress(FileNotFoundError, PermissionError):
nullcontext上下文管理器
- 当代码需要根据条件决定是否使用上下文管理器时,
nullcontext提供“空上下文”,避免重复代码1
2
3
4
5
6
7
8
9
10
11
12from contextlib import nullcontext
def process_data(data, use_file=True):
context = open('output.txt', 'w') if use_file else nullcontext()
with context as f:
if f:
f.write(str(data))
else:
print(f"直接输出:{data}")
process_data("临时数据", use_file=False)
process_data("重要数据", use_file=True)
ExitStack类
contextlib支持通过with语句嵌套或使用ExitStack批量管理多个上下文,尤其适合动态生成的资源列表1
2
3
4
5
6
7from contextlib import ExitStack
file_names = ('file1.txt', 'file2.txt', 'file3.txt')
with ExitStack() as stack:
files = [stack.enter_context(open(name, 'w')) for name in file_names]
for f in files:
f.write('示例内容')- 在这个例子中,
ExitStack会自动管理多个文件的上下文,确保在退出with块时所有文件都被正确关闭。
- 在这个例子中,