Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

With

🟦 1. 什么是 with?

with 用于自动处理 资源申请 -> 使用 -> 释放 的流程。

with resource as r:
    r.do()

好处:

  • 自动关闭文件、连接、游标等
  • 避免泄漏
  • 避免 finally
  • 代码更简洁、可读性更高

🟩 2. 最常见的例子:文件

with open("data.txt", "r") as f:
    content = f.read()

离开缩进块后:

  • 自动调用 f.close()

🟦 3. with 背后的协议(必须掌握)

要让一个对象能被 with 使用,它必须实现:

__enter__(self)
__exit__(self, exc_type, exc, tb)

流程:

with obj as x:
    # 进入前会执行:x = obj.__enter__()
    # 离开时一定执行:obj.__exit__()

🟩 4. 自定义一个上下文管理器(你项目会用到)

class MyTimer:
    def __enter__(self):
        import time
        self.start = time.time()
        return self

    def __exit__(self, exc_type, exc, tb):
        import time
        print("耗时:", time.time() - self.start)
        # 返回 False 表示异常继续往外抛
        return False


with MyTimer():
    print("doing something...")

输出:

doing something...
耗时: 0.00123

🟦 5. 更优雅写法:contextlib.contextmanager

适合快速写 with:

from contextlib import contextmanager

@contextmanager
def open_db():
    conn = create_connection()
    try:
        yield conn
    finally:
        conn.close()

使用:

with open_db() as conn:
    conn.query(...)

🟩 6. with 的工程级使用场景

① 文件读取/写入

with open("a.txt") as f:
    ...

② 数据库连接/事务(你项目非常适用)

with SessionLocal() as session:
    session.add(...)
    session.commit()

③ 锁

from threading import Lock

lock = Lock()

with lock:
    # 自动 acquire / release

④ 网络连接(requests)

with requests.get(url, stream=True) as resp:
    ...

⑤ 处理临时资源

from tempfile import TemporaryDirectory

with TemporaryDirectory() as tmpdir:
    ...

⑥ 异常处理封装

from contextlib import suppress

with suppress(FileNotFoundError):
    os.remove("test.txt")

🟦 7. 上下文中的异常处理原理

__exit__ 接收三个参数:

参数 说明
exc_type 异常类型
exc 异常对象
tb traceback

如果 __exit__ 返回 True:

  • 异常被认为“已处理”,不会向上抛出

例如:

class IgnoreError:
    def __exit__(self, exc_type, exc, tb):
        return True   # 丢弃异常

🟩 8. with + 多个上下文

with open("a.txt") as f1, open("b.txt") as f2:
    ...

🟦 9. 关键:with 不会捕获异常,而是把它“交给” exit

你可以选择:

  • 不处理(返回 False)
  • 吃掉异常(返回 True)
  • 自己抛出新异常

🟩 10. 工程最佳实践(非常重要)

优先使用 with 管理 IO / DB / 网络资源

避免手动 close

自定义上下文管理器简化大量重复逻辑

如你常用的 Database session

避免在 with 块里写太多逻辑

原则:with 块越小越好

如果要确保执行清理操作,就用 with

比如锁、临时文件、网络流

🟦 11. 速查表(收藏)

功能 写法
文件操作 with open(...) as f:
自定义类 定义 __enter__ + __exit__
快速自定义 @contextmanager
忽略异常 with suppress(Exception):
管理锁 with lock:
数据库会话 with Session() as s:
多上下文 with A() as a, B() as b:
退出清理 写在 __exit__() 或 finally