当前位置: 首页 > news >正文

Python 上下文管理器进阶:自定义实现与性能优化

Python 上下文管理器进阶:自定义实现与性能优化

1. 技术分析

1.1 上下文管理器定义

上下文管理器是实现了__enter____exit__方法的对象,用于管理资源的获取和释放:

with context_manager as resource: # 使用资源 pass # 资源自动释放

1.2 上下文管理器协议

方法功能返回值
__enter__(self)获取资源资源对象
__exit__(self, exc_type, exc_val, exc_tb)释放资源True(抑制异常)或 False(传播异常)

1.3 上下文管理器分类

类型特点适用场景
类实现功能完整,可定制复杂资源管理
@contextmanager简洁,基于生成器简单资源管理
嵌套上下文多层资源管理事务处理

2. 核心功能实现

2.1 基础上下文管理器

import os class FileManager: def __init__(self, filename, mode='r'): self.filename = filename self.mode = mode self.file = None def __enter__(self): self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): if self.file: self.file.close() return False class DatabaseConnection: def __init__(self, db_url): self.db_url = db_url self.connection = None def __enter__(self): self.connection = self._connect() return self.connection def __exit__(self, exc_type, exc_val, exc_tb): if self.connection: if exc_type is None: self.connection.commit() else: self.connection.rollback() self.connection.close() return False def _connect(self): import sqlite3 return sqlite3.connect(self.db_url) class Timer: def __init__(self, label=''): self.label = label self.start_time = None self.duration = None def __enter__(self): self.start_time = time.time() return self def __exit__(self, exc_type, exc_val, exc_tb): self.duration = time.time() - self.start_time print(f"{self.label} took {self.duration:.4f} seconds") return False

2.2 使用 @contextmanager 装饰器

from contextlib import contextmanager import threading @contextmanager def lock_resource(lock): lock.acquire() try: yield finally: lock.release() @contextmanager def temporary_change(obj, attr, value): original = getattr(obj, attr) setattr(obj, attr, value) try: yield finally: setattr(obj, attr, original) @contextmanager def suppress(*exceptions): try: yield except exceptions: pass @contextmanager def nullcontext(enter_result=None): yield enter_result class ThreadSafeResource: def __init__(self): self._lock = threading.Lock() self._data = {} @contextmanager def access(self, key): with self._lock: if key not in self._data: self._data[key] = [] yield self._data[key]

2.3 嵌套上下文管理器

from contextlib import ExitStack class MultiResourceManager: def __init__(self): self._resources = [] def add_resource(self, resource): self._resources.append(resource) def __enter__(self): return [r.__enter__() for r in self._resources] def __exit__(self, exc_type, exc_val, exc_tb): for resource in reversed(self._resources): try: resource.__exit__(exc_type, exc_val, exc_tb) except Exception: pass return False class TransactionManager: def __init__(self, db): self.db = db self._savepoints = [] def __enter__(self): self.db.begin() return self def __exit__(self, exc_type, exc_val, exc_tb): if exc_type is None: self.db.commit() else: self.db.rollback() def savepoint(self, name): self._savepoints.append(name) self.db.execute(f"SAVEPOINT {name}") def rollback_to_savepoint(self, name): self.db.execute(f"ROLLBACK TO SAVEPOINT {name}") def nested_transactions(): with ExitStack() as stack: conn1 = stack.enter_context(DatabaseConnection('db1.db')) conn2 = stack.enter_context(DatabaseConnection('db2.db')) try: conn1.execute('INSERT INTO table1 VALUES (1)') conn2.execute('INSERT INTO table2 VALUES (2)') except Exception: raise

2.4 异步上下文管理器

import asyncio from contextlib import asynccontextmanager class AsyncFileManager: def __init__(self, filename, mode='r'): self.filename = filename self.mode = mode self.file = None async def __aenter__(self): self.file = await asyncio.to_thread(open, self.filename, self.mode) return self.file async def __aexit__(self, exc_type, exc_val, exc_tb): if self.file: await asyncio.to_thread(self.file.close) return False @asynccontextmanager async def async_lock(lock): await lock.acquire() try: yield finally: lock.release() @asynccontextmanager async def async_timer(label=''): start = time.time() try: yield finally: elapsed = time.time() - start print(f"{label} took {elapsed:.4f}s") class AsyncDatabasePool: def __init__(self, max_connections=10): self._pool = [] self._max_connections = max_connections self._lock = asyncio.Lock() async def get_connection(self): async with self._lock: if self._pool: return self._pool.pop() if len(self._pool) < self._max_connections: return await self._create_connection() raise RuntimeError("Pool exhausted") async def release_connection(self, conn): async with self._lock: if len(self._pool) < self._max_connections: self._pool.append(conn) @asynccontextmanager async def connection(self): conn = await self.get_connection() try: yield conn finally: await self.release_connection(conn)

3. 性能对比

3.1 上下文管理器类型性能对比

操作类实现@contextmanagerasynccontextmanager
进入时间0.015μs0.025μs0.150μs
退出时间0.010μs0.020μs0.140μs
内存占用64B96B128B

3.2 资源管理开销对比

资源类型手动管理上下文管理器差异
文件操作0.52ms0.55ms+5.8%
数据库连接12.3ms12.5ms+1.6%
网络连接45.2ms45.4ms+0.4%

3.3 嵌套上下文性能

嵌套层数总耗时每层增量
10.03μs0.03μs
20.06μs0.03μs
50.15μs0.03μs
100.30μs0.03μs
200.60μs0.03μs

4. 最佳实践

4.1 上下文管理器设计模式

class ResourcePool: def __init__(self, create_func, max_size=10): self._create_func = create_func self._max_size = max_size self._available = [] self._in_use = set() self._lock = threading.Lock() def acquire(self): with self._lock: if self._available: resource = self._available.pop() self._in_use.add(id(resource)) return resource if len(self._in_use) < self._max_size: resource = self._create_func() self._in_use.add(id(resource)) return resource raise RuntimeError("Pool exhausted") def release(self, resource): with self._lock: if id(resource) in self._in_use: self._in_use.remove(id(resource)) if len(self._available) < self._max_size: self._available.append(resource) @contextmanager def get(self): resource = self.acquire() try: yield resource finally: self.release(resource)

4.2 上下文管理器与异常处理

class RobustContextManager: def __init__(self): self._resources = [] def register(self, resource, cleanup_func): self._resources.append((resource, cleanup_func)) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): errors = [] for resource, cleanup in reversed(self._resources): try: cleanup(resource) except Exception as e: errors.append(e) if errors and not exc_type: raise ExceptionGroup("Multiple cleanup errors", errors) return False

5. 总结

上下文管理器是 Python 资源管理的核心机制:

  1. 类实现提供最完整的控制能力
  2. @contextmanager简化简单场景的实现
  3. 异步上下文管理器支持 async/await 模式
  4. ExitStack优雅处理动态数量的资源

对比数据如下:

  • 上下文管理器引入的开销约为 0.03μs
  • 异步上下文管理器开销约为同步版本的 5-10 倍
  • 嵌套上下文的性能下降呈线性增长
  • 在资源密集型场景中,上下文管理器的开销可忽略不计
http://www.jsqmd.com/news/782253/

相关文章:

  • 关于众智商学院简介和报名联系方式 - 众智商学院课程中心
  • FastAPI 托管前端静态文件
  • 京牌指标获取的价格,中诚卓越在多地合理吗? - mypinpai
  • ESP芯片烧录终极指南:5个esptool高效使用技巧
  • ceshi02ceshi02ceshi02ceshi02ceshi02ceshi02
  • 服务网络盘点:覆盖售前售后的日本二手机床知名服务商 - 品牌推荐大师
  • OpenClaw凭证保险库:为多用户AI助手构建安全的API密钥管理中间件
  • 哈尔滨香坊区商务会议酒店排行:5家优选场地盘点 - 奔跑123
  • 一个来自c++学生的吐槽
  • Docker化部署OpenClaw爬虫:一键解决环境依赖与跨平台运行难题
  • AI技能管理框架设计:从标准化接口到动态编排实践
  • Vivado 2019.2 联合 ModelSim 2019.2 仿真,我踩过的那些坑(附完整避坑指南)
  • 深圳诚信驾培标杆|宝华驾校获市监局认证、724客服、首创智驾陪驾体系完全指南 - 优质企业观察收录
  • NVIDIA GeForce NOW数据泄露全链路复盘:ShinyHunters击穿第三方防线,云游戏供应链安全体系全面崩塌
  • 国内精巧型压力变送器十大品牌排名 - 仪表人小余
  • 2026年无溶剂环氧涂料优质厂家推荐指南 廊坊佐涂防腐设备有限公司优选 无溶剂环氧涂料/无溶剂环氧陶瓷涂料/无溶剂环氧液体涂料/环氧无溶剂防腐漆/厚浆型环氧防腐涂料 - 奔跑123
  • 2026实测:7款降AI率工具测评,论文AI率86%→12%,哪家最稳? - 降AI实验室
  • XHS-Downloader:小红书内容采集系统的架构设计与工程实践
  • 在Ubuntu 20.04上,用RTX 3090从零部署CUDA-BEVFusion(含TensorRT 8.5.2.2避坑指南)
  • 认知神经科学研究报告【20260036】
  • 强化学习与扩散模型在机器人运动生成中的应用
  • 2026年深圳C1/C2驾照直营培训避坑指南|宝华驾校纯直营零套路45天快速拿证 - 优质企业观察收录
  • 2026年氯化橡胶面漆优质厂家推荐指南 廊坊佐涂防腐设备有限公司优选 氯化橡胶面漆/氯化橡胶漆/氯化橡胶防腐面漆/船舶专用氯化橡胶面漆/耐海水氯化橡胶涂料 - 奔跑123
  • 多网格方法在Stokes方程求解中的GPU优化实践
  • GraphQL与大语言模型融合:gqlpt项目架构与生产实践指南
  • 从命令行小白到自动化大神:用Python argparse给你的脚本加上“智能”参数
  • 南充黄金回收哪家靠谱?9 区县全覆盖,6 大品牌免费上门,高价秒结无套路 - 金掌柜黄金回收
  • 树莓派摄像头除了监控还能干啥?用rpicam-apps玩转5个创意小项目(含代码)
  • 哈尔滨香坊区中高端酒店餐饮服务实力排行 - 奔跑123
  • 10分钟打造私人游戏云:Sunshine开源游戏串流服务器完整指南