当前位置:首页>python>Python编程基础(上下文管理器)

Python编程基础(上下文管理器)

  • 2026-10-11 07:02:03
Python编程基础(上下文管理器)

1,with是什么:

with 语句是 Python 提供的一种上下文管理器(Context Manager) 语法,用于自动管理资源的获取和释放。它可以确保某些"清理"操作(如关闭文件、释放锁、断开连接等)无论代码是否发生异常,都一定会被执行。

为什么要使用with?

举个例子,打开一个文件写入内容通常语下面三种做法:

最简单的方式:

# ❌ 不使用 with:需要手动关闭,且异常时可能忘记关闭f = open('test.txt', 'r')data = f.read()# 如果这里抛出异常,f.close() 就不会执行 → 资源泄漏f.close()

使用try/finally:

# ✅ 使用 try/finally:可以保证关闭,但代码冗长f = open('test.txt', 'r')try:    data = f.read()finally:    f.close()

使用with时:

# ✅ 使用 with:简洁 + 安全withopen('test.txt', 'r') as f:    data = f.read()# 离开 with 块时,f 自动关闭(即使发生异常)

2,with语句背后的工作原理:

with 语句背后依赖两个"魔法方法"(协议方法):

方法
调用时机
作用
__enter__(self)
进入 with 块时
获取资源,返回值赋给 as 后的变量
__exit__(self, exc_type, exc_val, exc_tb)
离开 with 块时(正常或异常)
释放资源,异常处理

__exit__ 的三个参数

  • exc_type:异常类型(无异常则为 None)

  • exc_val:异常实例

  • exc_tb:异常回溯对象(traceback)

  • 返回值:如果返回 True,异常会被"吞掉";否则异常正常向上抛出。

3,动手写with---上下文管理器

例子一:

class MyFile:    def __init__(self, filename, mode='r'):        self.filename = filename        self.mode = mode        self.file = None    def __enter__(self):        print(f"[进入] 打开文件: {self.filename}")        self.file = open(self.filename, self.mode, encoding='utf-8')        return self.file  # 返回值会被赋给 as 后面的变量    def __exit__(self, exc_type, exc_val, exc_tb):        print(f"[退出] 关闭文件: {self.filename}")        if self.file:            self.file.close()        # 如果有异常,打印出来,但不抑制(返回 False 或 None)        if exc_type is not None:            print(f"[异常] 类型={exc_type.__name__}, 信息={exc_val}")        return False  # 让异常正常向上抛出# 使用with MyFile('demo.txt', 'w') as f:    f.write("Hello, with statement!")    print("正在写入文件...")

输出为:

[进入] 打开文件: demo.txt正在写入文件...[退出] 关闭文件: demo.txt

例子二:

import timeclass Timer:    def __enter__(self):        self.start = time.time()        return self  # 返回自身,方便获取属性    def __exit__(self, exc_type, exc_val, exc_tb):        self.elapsed = time.time() - self.start        print(f"耗时: {self.elapsed:.4f} 秒")# 使用with Timer() as t:    total = sum(i * i for i in range(1_000_000))    print(f"计算结果: {total}")

输出为:

计算结果: 333332833333500000耗时: 0.0821 秒

例子三(项目中常见的使用方式,装饰器实现):

from contextlib import contextmanagerimport time@contextmanagerdef my_timer():    start = time.time()    try:        yield start          # yield 之前 = __enter__    finally:        elapsed = time.time() - start        print(f"耗时: {elapsed:.4f} 秒")   # yield 之后 = __exit__with my_timer() as start_time:    print(f"开始时间戳: {start_time}")    time.sleep(0.5)

输出为:

开始时间戳: 1785683961.641807耗时: 0.5003 秒

4,with 的高级用法

  1. 同时管理多个资源

with open('a.txt') as fa, open('b.txt') as fb:    data = fa.read() + fb.read()
  1. 常见的内置上下文管理器

场景
用法
文件
with open(...) as f:
线程锁
with lock:
数据库连接
with conn:
临时目录
with tempfile.TemporaryDirectory() as d:
抑制异常
with contextlib.suppress(FileNotFoundError):

此处的上下文管理器可以自己看看,后续也会陆续在项目中提到这些。

5、总结

要点
说明
本质
一种资源自动管理机制
协议
实现 __enter__ 和 __exit__ 即可
优势
简洁、安全、异常安全(exception-safe)
替代写法
使用 @contextmanager 装饰生成器函数
应用场景
文件、锁、连接、事务、计时、临时状态切换等

一句话记忆:with = 自动版的 try / finally,让"清理代码"永远不会被忘记执行。

最新文章

随机文章