详细介绍:with语句与上下文管理器:你用对了吗?
with语句与上下文管理器:你用对了吗?
作者:FeiLink
在处理文件、网络连接、数据库等需要资源释放的任务时,Python 提供了一个语法糖 —— with 语句。它的核心就是简洁、安全地管理资源,避免你“忘记关闭文件”、“未释放连接”等低级错误。
但你真的用对 with 了吗?你知道它背后其实就是一个上下文管理器(Context Manager)吗?本章我们就来从源码级别彻底理解它的原理与用法。
一、为什么需要 with?
传统文件操作写法:
f = open("example.txt", "r")
content = f.read()
f.close()
如果中间出错,比如读取时异常,f.close() 永远不会执行,资源泄露。
推荐写法:使用 with
with open("example.txt", "r") as f:
content = f.read()
# 文件自动关闭,无需手动调用 close()
✅ 优点:
- 出错时自动释放资源
- 代码简洁清晰
- 更符合“Pythonic”风格
二、with 语法结构解析
with 表达式 as 变量:
代码块
- 表达式:必须返回一个上下文管理器对象(即实现了
__enter__和__exit__方法的对象) - 变量:
__enter__方法的返回值,通常是资源对象,如文件、连接等 - 代码块:使用该资源进行操作的地方
三、模拟实现:自定义上下文管理器
class MyContext
:
def __enter__(self):
print("进入上下文:__enter__")
return "资源对象"
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文:__exit__")
if exc_type:
print(f"捕获异常:{exc_type.__name__
} ->
{exc_val
}")
return False # 是否抑制异常(False 表示不抑制)
with MyContext() as obj:
print("处理中:", obj)
# raise ValueError("模拟异常") # 取消注释试试
输出:
进入上下文:__enter__
处理中: 资源对象
退出上下文:__exit__
✅ 说明:
- 你可以控制是否“吞掉”异常
- 所有
with语句,内部都调用了这两个方法
❌ 四、错误写法示例
错误示例 1:忘记使用 with 导致资源未释放
f = open("data.txt", "r")
# 如果中间抛出异常,f.close() 永远不会执行
data = f.read()
# f.close() 可能永远不被调用
问题:如果读取数据中断,f 不会关闭,占用系统文件描述符
✅ 正确写法:
with open("data.txt", "r") as f:
data = f.read()
五、多个资源同时使用 with
with open("a.txt") as f1, open("b.txt") as f2:
data1 = f1.read()
data2 = f2.read()
Python 支持在一行中同时打开多个资源,自动管理多个上下文环境。
六、实战项目:自动备份脚本
任务:读取一个用户配置文件,生成 .bak 备份副本
def backup_file(filename):
try:
with open(filename, "r", encoding="utf-8") as src, \
open(filename + ".bak", "w", encoding="utf-8") as dst:
for line in src:
dst.write(line)
print("备份成功!")
except FileNotFoundError:
print("源文件不存在。")
except Exception as e:
print(f"出现错误:{e
}")
backup_file("settings.cfg")
实用性:
- 可扩展为批量备份、加密备份
- 支持编码设置与异常处理
七、进阶:使用 contextlib 简化上下文管理器
from contextlib import contextmanager
@contextmanager
def tag(name):
print(f"<
{name
}>")
yield
print(f"</{name
}>")
with tag("b"):
print("这是加粗文本")
输出:
这是加粗文本
优点:用生成器构造上下文,代码更灵活,适合轻量控制逻辑
面试延伸问题
__enter__和__exit__的调用顺序?- 如何手动实现一个上下文管理器类?
contextlib有什么用?和传统写法的区别?with支持嵌套使用吗?多个资源如何管理?__exit__中返回True和False有什么区别?
✅ 本章小结
with是 Python 管理资源的最佳实践- 它的本质是“上下文管理器”,通过
__enter__/__exit__控制资源获取与释放 - 推荐使用
contextlib编写轻量级上下文逻辑 - 所有涉及资源生命周期的场景都应该使用
with
本文部分内容由 AI 辅助生成,并经人工整理与验证,仅供参考学习,欢迎指出错误与不足之处。

浙公网安备 33010602011771号