Python上下文管理器通过__enter__和__exit__方法实现资源安全获取与确定性释放:__enter__在with开始时执行并返回绑定对象,__exit__在结束时必执行以清理资源并可选择抑制异常。

Python上下文管理器通过实现 __enter__ 和 __exit__ 两个特殊方法来控制进入和退出上下文的行为,核心在于资源的安全获取与确定性释放。
__enter__:负责初始化与资源获取
该方法在 with 语句开始执行时自动调用,通常用于打开文件、建立数据库连接、加锁等操作。它的返回值会绑定到 as 后的变量上。
- 若未显式返回值,默认返回
self(即当前对象) - 可返回任意对象,比如打开的文件对象、连接实例或一个简单的状态标识
- 若初始化失败(如文件不存在、网络不可达),应主动抛出异常,
with块不会执行后续代码
__exit__:统一处理清理与异常传播
该方法在 with 块结束时(无论是否发生异常)必定执行,接收三个参数:exc_type(异常类)、exc_value(异常实例)、traceback(回溯对象)。它们仅在发生异常时非 None。
- 正常退出时三者均为
None,适合做通用清理(如关闭句柄、提交/回滚事务) - 若返回
True,表示已“处理”了异常,Python 不再向上抛出;返回False或None(默认)则继续传播异常 - 注意:即使想忽略某个特定异常,也应在内部完成日志记录或补偿逻辑,避免静默吞掉错误
手动实现一个带错误抑制的临时目录管理器
以下是一个简明示例,展示如何组合两个方法实现安全、可控的上下文行为:
立即学习“Python免费学习笔记(深入)”;
import tempfile
import os
<p>class TempDir:
def <strong>enter</strong>(self):
self.path = tempfile.mkdtemp()
return self.path # 返回路径供 with as 使用</p><pre class="brush:php;toolbar:false;">def __exit__(self, exc_type, exc_val, exc_tb):
if os.path.exists(self.path):
try:
os.rmdir(self.path) # 尝试删除空目录
except OSError:
pass # 目录非空时不强求,也可改用 shutil.rmtree
# 不返回 True → 异常仍会抛出,保证错误可见性使用时:
with TempDir() as td:
print("临时目录:", td)
# 可能出错的操作...
@contextmanager 装饰器:更简洁的替代写法
对于逻辑简单、无需复用类的场景,可用 contextlib.contextmanager 装饰生成器函数,其中 yield 之前对应 __enter__,之后对应 __exit__ 的清理部分。
-
yield的值即为as接收的对象 -
yield后的代码总会在退出时执行,类似__exit__中的 finally 分支 - 若需拦截异常,可在
try/except中捕获并决定是否重新 raise










