脚本里有时会按条件打开好几个文件、临时目录,写一堆嵌套 with 会有点乱。contextlib.ExitStack 适合这种“资源数量运行时才知道”的场景,退出时会按反向顺序统一清理。
环境:Python 3.10+,Linux/macOS/Windows,只用标准库。保存为 exitstack-demo.py:
from contextlib import ExitStack
from pathlib import Path
from tempfile import TemporaryDirectory
def build_files(names):
with ExitStack() as stack:
tmp = Path(stack.enter_context(TemporaryDirectory()))
handles = []
for name in names:
path = tmp / f"{name}.txt"
handle = stack.enter_context(path.open("w+", encoding="utf-8"))
handle.write(f"hello {name}\n")
handle.seek(0)
handles.append(handle)
for handle in handles:
print(handle.read().strip())
print("tmp exists inside:", tmp.exists())
return tmp
old_tmp = build_files(["api", "worker", "cron"])
print("tmp exists after:", old_tmp.exists())
跑一下:
python3 exitstack-demo.py
输出大概是:
hello api
hello worker
hello cron
tmp exists inside: True
tmp exists after: False
这个比手写 try/finally 的好处是:中间任意一步抛异常,前面已经注册进去的资源也会正常退出。用在“循环里打开多个文件”“临时切换一组上下文”这种小工具里挺顺手。