ExitStack:运行时才知道数量的资源怎么清理
同时打开几份文件时可以嵌套 with,但数量由输入决定时,固定语法层级就不方便。资源获取到一半失败,也需要释放前面已经取得的资源。
问题从哪里出现
同时打开几份文件时可以嵌套 with,但数量由输入决定时,固定语法层级就不方便。资源获取到一半失败,也需要释放前面已经取得的资源。
理解核心机制
ExitStack 动态登记上下文或清理回调,并按逆序退出。每次成功获取后立即登记释放,能让部分初始化失败得到正确处理。
动手做一个小实验
Python 3.11 或更新版本,仅使用标准库;将示例保存为 demo.py 后执行 python3 demo.py。
from contextlib import ExitStack
from io import StringIO
handles = []
with ExitStack() as stack:
for text in ("alpha", "beta", "gamma"):
handles.append(stack.enter_context(StringIO(text)))
print([handle.read() for handle in handles])
assert all(handle.closed for handle in handles)适用边界与常见误区
回调顺序与上下文异常传播有关,不能随意把存在依赖的资源交换顺序。异步资源应考虑 AsyncExitStack,避免混用同步关闭协议。
继续练习
在获取第二个资源后抛异常,记录清理顺序;再用 callback 登记一个普通清理函数,比较两种登记方式。