当前位置:首页>python>一名 PHP 工程师的 Python 系统学习笔记(06):with 上下文管理器

一名 PHP 工程师的 Python 系统学习笔记(06):with 上下文管理器

  • 2026-08-24 14:40:17
一名 PHP 工程师的 Python 系统学习笔记(06):with 上下文管理器

一名 PHP 工程师的 Python 系统学习笔记(06):with 上下文管理器

真正把 Python 写“干净”,with 是绕不过去的一关。

很多人对 with 的理解只停留在:

with open("a.txt") as f:    data = f.read()

能用,但不知道为什么要用。

这一篇只做一件事:把 with 在工程里的价值讲清楚。


一、先抛结论:with 解决的是什么问题?

一句话总结:

保证资源一定被正确释放。

不管中间代码:

  • 正常执行
  • 抛异常
  • 提前 return

资源都能被回收。


二、不用 with 的典型问题

f = open("a.txt")try:    data = f.read()finally:    f.close()

这段代码本身没错,但有 3 个问题:

  • 模板代码重复
  • 容易漏写
  • 可读性差

👉 with 的意义,是把这类模板代码抽走。


三、with 的本质:上下文管理协议

任何对象,只要实现了这两个方法,就能配合 with 使用:

__enter__()__exit__(exc_type, exc, tb)

执行顺序只有一句话:

进入时调用 __enter__,离开时一定调用 __exit__。


四、自己实现一个最小上下文管理器

classTimer:def__enter__(self):        self.start = time.time()return selfdef__exit__(self, exc_type, exc, tb):        cost = time.time() - self.start        print(f"cost: {cost}")
with Timer():    work()

工程意义:

👉 用语法结构,约束资源的生命周期。


五、异常在 with 中是如何处理的?

__exit__ 的返回值,决定异常是否继续抛出:

def__exit__(self, exc_type, exc, tb):returnTrue# 吞掉异常

工程建议:

👉 99% 的情况下,不要吞异常。

with 的职责是清理资源,不是隐藏错误。


六、contextlib:更轻量的写法

from contextlib import contextmanager@contextmanagerdeftimer():    start = time.time()yield    print(time.time() - start)
with timer():    work()

在 @contextmanager 语义下: yield 之前 → enteryield 之后 → exit

with timer(): ↓ yield ↓ 离开 with

这是 “生成器 + 装饰器 + 异常处理” 的组合体。

👉 非常 Pythonic。


七、工程中常见的 with 场景

你在项目里见到的这些,几乎都是上下文管理器:

  • 文件操作
  • 数据库连接 / 事务
  • 锁(Lock)
  • 临时目录
  • 会话(Session)

八、这一篇你只需要记住 5 件事

  1. with 是资源管理工具
  2. 本质是 __enter__ / __exit__
  3. 异常一定会经过 __exit__
  4. 不要滥用“吞异常”
  5. contextlib 适合轻量场景

写在最后

如果你已经理解了:

  • 装饰器
  • 异常处理
  • with

那么你已经掌握了 Python 工程级语法的核心三件套。

下一篇,我会继续写一个和性能、可维护性高度相关的话题:

迭代器与生成器:为什么 Python 能写得这么省内存

如果你也是从 PHP / Go 转 Python,希望这个系列能真正形成你的“第二语言直觉”。

最新文章

随机文章