上下文管理器:异常路径也要释放资源
把清理动作写在函数末尾,无法覆盖中途抛异常的情况。with 语句把资源作用域放到语法结构里,退出时调用清理协议。
▶ 本文含视频讲解▶ 教学视频手动播放 · 英语讲解
Learn Python — Full Course for Beginners
Python 入门课程作为语法与编程背景复习;本文使用的较新标准库特性不保证在该课程中逐项覆盖。此为外部原版课程,多篇笔记可能共用;未剪辑为本文专属视频。
播放器需要能访问 YouTube 的网络;若这里无法加载,可打开原视频。本文与本地图解仍可独立阅读。
问题从哪里出现
把清理动作写在函数末尾,无法覆盖中途抛异常的情况。with 语句把资源作用域放到语法结构里,退出时调用清理协议。
理解核心机制
contextmanager 装饰器可以把获取、yield 和释放组合起来。释放部分通常放进 finally,这样正常返回和异常退出都会执行。不要无意吞掉主体异常。
动手做一个小实验
Python 3.11 或更新版本,仅使用标准库;将示例保存为 demo.py 后执行 python3 demo.py。
from contextlib import contextmanager
events = []
@contextmanager
def resource():
events.append("open")
try:
yield "handle"
finally:
events.append("close")
try:
with resource() as handle:
raise ValueError(handle)
except ValueError:
pass
assert events == ["open", "close"]
print(events)适用边界与常见误区
清理函数自身也可能失败,甚至遮蔽原始错误。数据库提交与关闭是不同操作,不能用资源释放代替事务设计。
继续练习
让主体分别正常结束、提前返回和抛出异常,记录清理次数,确保每条路径恰好执行一次。