Python 的 @contextmanager
装饰器(来自 contextlib
模块)通过生成器简化了上下文管理器的创建。它的核心原理是将生成器的 yield
语句拆分为 __enter__
和 __exit__
两个阶段,最终生成一个符合上下文协议的对象。
核心步骤
-
生成器分段:
yield
前的代码对应__enter__
逻辑(资源分配)。yield
后的代码对应__exit__
逻辑(资源清理)。
-
装饰器魔法:
from contextlib import contextmanager @contextmanager def my_context(): print("Enter") # __enter__ 阶段 yield "资源" # 暂停,返回资源 print("Exit") # __exit__ 阶段
-
执行流程:
with my_context() as res: print("Using", res) # 输出: # Enter # Using 资源 # Exit
等价于类实现
@contextmanager
生成的上下文管理器等价于:
class MyContext:
def __enter__(self):
print("Enter")
return "资源"
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exit")
return False # 不抑制异常
异常处理
装饰器自动处理异常传播:
yield
后的代码会在__exit__
中执行,无论 with 块是否抛出异常。- 若需捕获异常,可在生成器中使用
try...finally
:@contextmanager def safe_open(): resource = acquire_resource() try: yield resource finally: release_resource(resource) # 确保资源释放
关键优势
- 代码简洁:无需手动实现
__enter__
/__exit__
。 - 逻辑直观:用线性代码表达资源生命周期。
- 轻量级:适合快速创建一次性上下文管理器。
理解这一机制后,可以更灵活地利用生成器控制资源管理边界。