Python
基础语法
01概念
02安装
03变量
04字符串
05数
06常量与注释
07列表
08元组
09if语句
10字典
11集合
12复合数据类型对比
13推导式
14用户输入
15while循环
16函数
17类
18面向对象编程
19文件操作
20异常处理
21日期和时间
22魔术方法
23内置函数
24线程
25并发&并行
26正则表达式
27迭代器
28装饰器
29生成器
30上下文管理器
31函数式编程
32闭包
33解包
34工具库
35连接关系型数据库
36虚拟环境
37异步编程
网络爬虫
01urllib库[了解]
02requests库
03数据交换格式
04解析库
05lxml
06Beautiful Soup
07Xpath语法
08动态网页的处理
-
+
首页
30上下文管理器
在 Python 中,**上下文管理器(Context Manager)** 是一种用于**安全管理资源**(如文件、数据库连接、网络连接、锁等)的机制。它通过预定义的协议,确保资源在使用完毕后**自动释放**,无论使用过程中是否发生异常,从而避免资源泄露(如文件未关闭、数据库连接未释放等问题)。 上下文管理器的核心优势在于:**简化资源管理代码**(无需手动编写try-finally块)、**确保资源释放的可靠性**(即使发生错误也能执行清理操作)。 ## 核心协议 上下文管理器必须实现**上下文管理协议**,即定义两个特殊方法: \_\_enter\_\_(self):进入 “上下文”(如with语句块)时调用,负责**准备资源**(如打开文件、建立连接),并返回一个与资源相关的对象(可通过as关键字接收)。 \_\_exit\_\_(self, exc_type, exc_val, exc_tb):离开 “上下文”(如with语句块执行完毕或异常退出)时调用,负责**释放资源**(如关闭文件、断开连接),并处理可能的异常。 - exc_type:异常类型(如ValueError); - exc_val:异常实例(包含错误信息); - exc_tb:异常的回溯对象(包含调用栈信息)。 \_\_exit\_\_的返回值为布尔值: - 若返回True:表示异常已被处理,不会向外传播; - 若返回False(默认):表示异常未处理,会继续向外抛出。 ## with语句 上下文管理器通常通过with语句使用,语法如下: ```python with 上下文管理器 as 变量: # 使用资源的代码块(上下文内) 操作变量 # 离开上下文,自动执行__exit__释放资源 ``` **执行流程**: 1. 执行with后的表达式,获取上下文管理器对象; 2. 调用管理器的\_\_enter\_\_()方法,准备资源,返回值赋给as后的变量; 3. 执行with块内的代码(使用资源); 4. 无论块内代码是否正常执行或抛出异常,均调用管理器的__exit__()方法释放资源。 例如:文件操作,文件对象是 Python 内置的上下文管理器,使用with语句操作文件可确保自动关闭,无需手动调用close(): ```python # 传统方式(需手动关闭,可能因异常导致未关闭) f = open("test.txt", "r") try: content = f.read() finally: f.close() # 必须手动关闭 # 上下文管理器方式(自动关闭,更安全简洁) with open("test.txt", "r") as f: content = f.read() # 块内使用文件 # 离开块后,自动调用f.close(),无论是否发生异常 ``` ## 实现方式 **方式 1:通过类实现(自定义上下文管理器)** 定义一个类,实现\_\_enter\_\_和\_\_exit\_\_方法,即可作为上下文管理器。 例如:自定义数据库连接上下文管理器。 ```python import pymysql class DatabaseConnection: def __init__(self, host, user, password, db): self.config = { "host": host, "user": user, "password": password, "db": db } self.conn = None # 数据库连接对象 def __enter__(self): # 建立连接(准备资源) self.conn = pymysql.connect(**self.config) return self.conn # 返回连接对象,供with块使用 def __exit__(self, exc_type, exc_val, exc_tb): # 关闭连接(释放资源) if self.conn: self.conn.close() # 处理异常(若有) if exc_type: print(f"发生异常:{exc_type} - {exc_val}") # 返回True表示异常已处理,不向外传播 # return True # 使用自定义上下文管理器 with DatabaseConnection("localhost", "root", "password", "test_db") as conn: cursor = conn.cursor() cursor.execute("SELECT * FROM users") print(cursor.fetchone()) # 离开块后,自动关闭连接,即使查询过程中发生异常 ``` **方式 2:通过contextlib.contextmanager装饰器** 对于简单的资源管理逻辑,可使用contextlib模块的contextmanager装饰器,将**生成器函数**转换为上下文管理器,无需手动定义类和协议方法。 **原理**:生成器函数中,yield之前的代码相当于\_\_enter\_\_(准备资源),yield返回的值相当于\_\_enter\_\_的返回值;yield之后的代码相当于\_\_exit\_\_(释放资源)。 ```python from contextlib import contextmanager @contextmanager def file_manager(file_path, mode): # yield前:相当于__enter__,准备资源 f = open(file_path, mode) try: yield f # 返回文件对象,供with块使用 finally: # yield后:相当于__exit__,释放资源 f.close() print("文件已关闭") # 使用装饰器实现的上下文管理器 with file_manager("test.txt", "w") as f: f.write("Hello, context manager!") # 离开块后,自动执行finally中的close() ``` ## 高级用法 **1. 处理异常(\_\_exit\_\_的异常控制)** \_\_exit\_\_方法可决定是否捕获异常。例如,在数据库操作中,若发生错误可自动回滚事务: ```python class DBTransaction: def __init__(self, conn): self.conn = conn def __enter__(self): return self.conn # 返回连接,用于执行SQL def __exit__(self, exc_type, exc_val, exc_tb): if exc_type: self.conn.rollback() # 发生异常,回滚事务 print("事务已回滚") return True # 捕获异常,不向外传播 else: self.conn.commit() # 无异常,提交事务 print("事务已提交") # 使用事务上下文管理器 with DatabaseConnection(...) as conn: # 复用前面的连接管理器 with DBTransaction(conn): cursor = conn.cursor() cursor.execute("INSERT INTO users (name) VALUES ('Alice')") # 若此处发生异常(如主键冲突),会自动回滚 ``` **2. 嵌套上下文管理器** contextlib提供了多个预定义的上下文管理器,简化常见场景: - contextlib.closing(obj):将具有close()方法的对象转换为上下文管理器(自动调用close())。 ```python from contextlib import closing import some_library # 假设该库的连接对象有close()但无上下文协议 with closing(some_library.connect()) as conn: # 使用conn,离开块后自动调用conn.close() conn.do_something() ``` contextlib.suppress(*exceptions):临时忽略指定异常(无需写try-except): ```python from contextlib import suppress # 忽略FileNotFoundError,尝试删除文件 with suppress(FileNotFoundError): os.remove("temp.txt") # 若文件不存在,不报错 ``` contextlib.nullcontext():空上下文管理器(不做任何操作,用于条件性上下文): ```python from contextlib import nullcontext # 条件性使用锁:若需要同步,则用锁;否则用空上下文 use_lock = True ctx = lock if use_lock else nullcontext() with ctx: # 执行操作:若use_lock=True则加锁,否则无锁 process_data() ``` ## 适用场景 上下文管理器几乎适用于所有需要 “**获取资源 - 使用资源 - 释放资源**” 的场景,核心应用包括: 1. **文件操作**:自动关闭文件(避免句柄泄露); 2. **数据库操作**:自动断开连接、提交 / 回滚事务; 3. **网络连接**:自动关闭 Socket、HTTP 连接; 4. **线程 / 进程同步**:自动获取 / 释放锁(如threading.Lock是上下文管理器); 5. **临时资源**:创建临时文件 / 目录,使用后自动删除(tempfile模块的临时对象); 6. **状态管理**:临时修改全局状态(如临时设置环境变量,离开后恢复)。
毛林
2025年9月7日 11:45
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码