1. 什么是上下文管理器? #

# 以只读模式打开文件,退出 with 时自动关闭
with open("file.txt", "r", encoding="utf-8") as f:
    # 读取文件全部内容
    content = f.read()
# 文件已自动关闭

2. contextlib 模块 #

3. @contextmanager 基本用法 #

# 从 contextlib 导入 contextmanager 装饰器
from contextlib import contextmanager

# 用装饰器将生成器函数转为上下文管理器
@contextmanager
def my_context():
    # 进入 with 时执行的准备工作
    print("进入 with,做准备工作")
    try:
        # 将值传给 as 后面的变量
        yield "你好"
    finally:
        # 退出 with 时执行的清理工作(无论是否异常)
        print("退出 with,做清理工作")

# 使用自定义上下文管理器,msg 接收 yield 的值
with my_context() as msg:
    print("在 with 块内:", msg)

执行顺序:

进入 with,做准备工作
在 with 块内: 你好
退出 with,做清理工作

4. 实用示例:计时器 #

# 导入 contextmanager 装饰器
from contextlib import contextmanager
# 导入 time 模块用于高精度计时
import time

# 定义带可选标签的计时器上下文管理器
@contextmanager
def timer(label: str = ""):
    # 记录进入 with 时的时间戳
    start = time.perf_counter()
    try:
        # 将控制权交给 with 块内的代码
        yield
    finally:
        # 计算耗时(秒)
        elapsed = time.perf_counter() - start
        # 有标签时添加前缀,否则为空字符串
        prefix = f"[{label}] " if label else ""
        # 打印耗时,保留三位小数
        print(f"{prefix}耗时: {elapsed:.3f} 秒")

# 在计时器上下文中执行业务逻辑
with timer("数据处理"):
    # 模拟耗时操作
    time.sleep(0.5)
    print("执行业务逻辑...")

5. closing:自动关闭资源 #

# 导入 closing,为有 close() 方法的对象提供 with 支持
from contextlib import closing

# 模拟一个需要手动关闭的资源类
class SimpleResource:
    def __init__(self):
        print("资源已打开")
    def close(self):
        print("资源已关闭")

# 退出 with 时自动调用 close()
with closing(SimpleResource()):
    print("正在使用资源...")
# 自动调用 close()

6. suppress:忽略指定异常 #

# 导入 suppress,用于静默忽略指定异常
from contextlib import suppress
# 导入 os 模块进行文件操作
import os

# 等价于 try/except FileNotFoundError: pass,但更简洁
with suppress(FileNotFoundError):
    # 删除可能不存在的文件,不存在时不报错
    os.remove("可能不存在的文件.txt")

# 无论文件是否存在,程序都会继续执行
print("程序继续执行")

7. 注意事项 #

8. 总结 #