Python 的 with open() 能自动关闭文件,靠的是上下文管理协议,核心是 enter 和 exit 方法;执行时先调用 __enter__,再执行代码块,最后必调用含 close() 的 __exit__,确保异常下也安全关闭。

Python 的 with open() 能自动关闭文件,靠的是上下文管理协议(Context Manager Protocol),核心是对象的 __enter__ 和 __exit__ 方法。只要文件对象实现了这个协议(open() 返回的 TextIOWrapper 或 BufferedReader 等都实现了),即使代码中途出错、提前 return 或遇到异常,__exit__ 都会被调用,从而安全关闭文件。
with 语句背后发生了什么
执行 with open(...) as f: 时,Python 实际做了三件事:
- 调用
open()创建文件对象,并立即调用它的__enter__()方法(通常返回自身) - 执行缩进内的代码块
- 无论是否发生异常,都会在退出代码块前调用该对象的
__exit__(exc_type, exc_val, exc_tb)
而 __exit__ 的实现里就包含 self.close() —— 这就是关闭动作发生的确定位置。
不依赖 with 会有什么风险
手动调用 open() 后忘记 .close(),或在异常路径中遗漏关闭,会导致:
立即学习“Python免费学习笔记(深入)”;
- 文件描述符泄漏(尤其在循环或长期运行服务中可能耗尽系统资源)
- 写入缓冲区未刷新(
f.write()后没close()或flush(),内容可能丢失) - Windows 下无法再次打开同一文件(因系统锁未释放)
异常情况也可靠
下面这段代码即使报 ZeroDivisionError,文件依然会被关闭:
with open("data.txt", "w") as f:
f.write("hello")
1 / 0 # 触发异常
# 此处 f 已关闭,无需额外处理
什么时候不能只靠 with
绝大多数场景 with 完全够用,但需注意:
- 如果需要跨多个函数传递文件对象并延迟关闭,
with不适用(此时应显式管理生命周期) - 极少数自定义文件类未正确定义
__exit__,可能导致关闭失败(标准库类型无此问题) -
with只保证「退出时关闭」,不保证「实时写入」;若需立即落盘,仍要调用f.flush()










