2026/3/15 8:59:01
网站建设
项目流程
做网站 最好的开源cms,网站与网页设计教程,成品网站1688网页,网站空间购买 北京一、contextmanager有什么用#xff1f;
contextmanager是 Python 标准库contextlib模块提供的同步上下文管理器装饰器#xff0c;核心作用是简化同步上下文管理器的实现。
在没有contextmanager之前#xff0c;实现一个上下文管理器需要手动定义类#xff0c;并实现__ente…一、contextmanager有什么用contextmanager是 Python 标准库contextlib模块提供的同步上下文管理器装饰器核心作用是简化同步上下文管理器的实现。在没有contextmanager之前实现一个上下文管理器需要手动定义类并实现__enter__()和__exit__()两个魔法方法而使用contextmanager只需装饰一个同步生成器函数即可快速封装出上下文管理器无需手动实现魔法方法代码更简洁优雅。二、适用场景当你在同步代码中需要管理「需要先获取、使用后必须释放 / 清理」的资源时contextmanager是最优选择典型场景包括同步文件操作普通文件的打开 / 关闭自动释放文件句柄Python 内置open()本身就是上下文管理器此处用于演示封装思想同步数据库连接如pymysql操作 MySQL自动建立 / 关闭数据库连接同步锁 / 资源占用如threading.Lock自动获取 / 释放锁避免死锁临时资源创建 / 清理如临时目录创建、临时文件写入后自动删除、日志上下文切换等简单来说同步场景 资源需要自动管理获取 释放就用contextmanager。三、核心使用规则contextmanager装饰的同步生成器函数必须满足固定结构函数用def定义同步函数无async关键字函数内部包含且仅包含一个yield关键字用于分割「资源获取」和「资源释放」逻辑代码结构分为三部分yield 之前对应上下文管理器的__enter__()方法负责获取 / 初始化资源执行时机是进入with语句块时yield 关键字将需要使用的资源「返回」给with语句的as变量可返回单个资源也可返回None同时暂停函数执行交出控制权给with语句块yield 之后对应上下文管理器的__exit__()方法负责释放 / 清理资源执行时机是离开with语句块时无论代码块正常结束还是发生异常都会执行推荐将yield之后的清理逻辑放在finally块中确保资源释放的可靠性即使中间代码抛出异常清理逻辑也能执行四、代码示例我们实现一个「同步文件读写工具」使用contextmanager封装普通文件的打开 / 关闭确保文件句柄自动释放无需手动调用close()与之前的异步示例形成对比更易理解。# 1. 导入必要模块contextmanager是Python内置无需额外安装依赖fromcontextlibimportcontextmanager# 2. 使用contextmanager装饰同步生成器实现同步上下文管理器contextmanagerdeffile_manager(file_path:str,mode:strr,encoding:strutf-8): 同步文件管理器自动打开/关闭文件封装同步文件操作的资源管理 :param file_path: 文件路径 :param mode: 文件打开模式r/w/a等 :param encoding: 文件编码 # 初始化文件句柄file_handleNonetry:# -------- 第一步yield之前对应__enter__()获取/初始化资源 --------file_handleopen(file_path,modemode,encodingencoding)print(f✅ 同步打开文件{file_path}模式{mode})# -------- 第二步yield关键字返回资源给with语句暂停函数执行 --------yieldfile_handle# 将文件句柄传递给with ... as 后的变量# -------- 第三步yield之后对应__exit__()释放/清理资源finally确保必执行 --------finally:iffile_handle:file_handle.close()print(f❌ 同步关闭文件{file_path})# 3. 使用同步上下文管理器配合with语句defmain():# 测试文件路径test_file_pathtest_sync.txt# 示例1同步写入文件内容withfile_manager(test_file_path,modew)asf:f.write(Hello, contextmanager!\n)f.write(这是同步文件写入测试\n)# 示例2同步读取文件内容withfile_manager(test_file_path,moder)asf:contentf.read()print(\n 文件内容)print(content)# 4. 运行同步主函数if__name____main__:main()关键解析进入with语句块时自动执行yield之前的open()逻辑打开文件并获取文件句柄with语句块内操作文件句柄执行完成后自动离开代码块触发finally中的close()逻辑关闭文件即使文件写入 / 读取过程中抛出异常例如手动添加raise Exception(“测试异常”)finally块中的清理逻辑依然会执行确保文件句柄被释放不会造成资源泄露异常处理contextmanagerdeffile_manager(file_path:str,mode:strr,encoding:strutf-8):file_handleNonetry:file_handleopen(file_path,modemode,encodingencoding)print(f✅ 同步打开文件{file_path}模式{mode})yieldfile_handle# 此处抛出的异常会被传递到with代码块exceptFileNotFoundErrorase:print(f❌ 错误文件不存在 -{e})raise# 可选重新抛出异常让调用方感知并处理exceptExceptionase:print(f❌ 操作文件出错{e})raisefinally:iffile_handle:file_handle.close()print(f❌ 同步关闭文件{file_path})扩展示例演示contextmanager用于管理临时目录创建→使用→自动删除更贴近实际项目中的资源管理场景importosimportshutilfromcontextlibimportcontextmanagercontextmanagerdeftemporary_directory(dir_path:strtemp_dir):同步临时目录管理器自动创建→使用→删除临时目录# 1. 初始化创建临时目录try:os.makedirs(dir_path,exist_okTrue)print(f✅ 成功创建临时目录{dir_path})yielddir_path# 返回临时目录路径给with语句finally:# 2. 清理删除临时目录及其内容ifos.path.exists(dir_path):shutil.rmtree(dir_path)print(f❌ 成功删除临时目录{dir_path})# 使用临时目录deftest_temp_dir():withtemporary_directory()astemp_dir:# 在临时目录中创建文件temp_fileos.path.join(temp_dir,test.txt)withopen(temp_file,w)asf:f.write(临时文件内容)print(f 临时文件已创建{temp_file}文件大小{os.path.getsize(temp_file)}字节)if__name____main__:test_temp_dir()