Skip to content

文件、锁、连接这类资源,用之前要拿到,用完要还。忘了关,或者中途抛异常跳过关闭,都会留尾巴。with 把「进入」和「退出」收成一对。

不用 with:

python
file = open("test.py")
try:
    data = file.read()
finally:
    file.close()

用 with:

python
with open("test.py") as file:
    data = file.read()

文件关闭、异常路径,都由上下文管理器处理。

它怎么工作 ​

跟在 with 后面的对象要有 __enter__ 和 __exit__:

  1. 求值得到上下文管理器
  2. 调 __enter__,返回值赋给 as 后面的变量
  3. 跑代码块
  4. 无论是否异常,调 __exit__
python
class Simple:
    def __enter__(self):
        print("enter")
        return "ok"

    def __exit__(self, exc_type, exc_value, traceback):
        print("exit")

with Simple() as value:
    print("value:", value)

输出顺序是 enter → value: ok → exit。

异常 ​

__exit__ 的三个参数是异常类型、异常值、traceback。没有异常时三个都是 None。

python
class Simple:
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type is None:
            print("没有异常")
        else:
            print(exc_value)
        return True

    def boom(self):
        return 1 / 0

with Simple() as s:
    s.boom()

__exit__ 返回 True,异常被吞掉,外面看不到。返回 False 或 None,异常继续往外抛。开发库时,关文件、还锁、断连接,都适合放在 __exit__ 里。

测试开发工程师 · 专注自动化与系统架构 | 邮箱: hansblog@atumsoul.win