Python实现上下文管理器的方法


Posted in Python onAugust 07, 2020

问题

你想自己去实现一个新的上下文管理器,以便使用with语句。

解决方案

实现一个新的上下文管理器的最简单的方法就是使用 contexlib 模块中的 @contextmanager 装饰器。 下面是一个实现了代码块计时功能的上下文管理器例子:

import time
from contextlib import contextmanager

@contextmanager
def timethis(label):
  start = time.time()
  try:
    yield
  finally:
    end = time.time()
    print('{}: {}'.format(label, end - start))

# Example use
with timethis('counting'):
  n = 10000000
  while n > 0:
    n -= 1

在函数 timethis() 中,yield 之前的代码会在上下文管理器中作为 __enter__() 方法执行, 所有在 yield 之后的代码会作为 __exit__() 方法执行。 如果出现了异常,异常会在yield语句那里抛出。

下面是一个更加高级一点的上下文管理器,实现了列表对象上的某种事务:

@contextmanager
def list_transaction(orig_list):
  working = list(orig_list)
  yield working
  orig_list[:] = working

这段代码的作用是任何对列表的修改只有当所有代码运行完成并且不出现异常的情况下才会生效。 下面我们来演示一下:

>>> items = [1, 2, 3]
>>> with list_transaction(items) as working:
...   working.append(4)
...   working.append(5)
...
>>> items
[1, 2, 3, 4, 5]
>>> with list_transaction(items) as working:
...   working.append(6)
...   working.append(7)
...   raise RuntimeError('oops')
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
RuntimeError: oops
>>> items
[1, 2, 3, 4, 5]
>>>

讨论

通常情况下,如果要写一个上下文管理器,你需要定义一个类,里面包含一个 __enter__() 和一个 __exit__() 方法,如下所示:

import time

class timethis:
  def __init__(self, label):
    self.label = label

  def __enter__(self):
    self.start = time.time()

  def __exit__(self, exc_ty, exc_val, exc_tb):
    end = time.time()
    print('{}: {}'.format(self.label, end - self.start))

尽管这个也不难写,但是相比较写一个简单的使用 @contextmanager 注解的函数而言还是稍显乏味。

@contextmanager 应该仅仅用来写自包含的上下文管理函数。 如果你有一些对象(比如一个文件、网络连接或锁),需要支持 with 语句,那么你就需要单独实现 __enter__() 方法和 __exit__() 方法。

以上就是Python实现上下文管理器的方法的详细内容,更多关于Python实现上下文管理器的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python的Django框架中if标签的相关使用
Jul 15 Python
Python多图片合并PDF的方法
Jan 03 Python
Python面向对象思想与应用入门教程【类与对象】
Apr 12 Python
django框架防止XSS注入的方法分析
Jun 21 Python
检测python爬虫时是否代理ip伪装成功的方法
Jul 12 Python
django 实现将本地图片存入数据库,并能显示在web上的示例
Aug 07 Python
Python全局锁中如何合理运用多线程(多进程)
Nov 06 Python
使用TFRecord存取多个数据案例
Feb 17 Python
在Python中用GDAL实现矢量对栅格的切割实例
Mar 11 Python
Python稀疏矩阵及参数保存代码实现
Apr 18 Python
Python新手学习raise用法
Jun 03 Python
Python快速优雅的批量修改Word文档样式
May 20 Python
Python 读取位于包中的数据文件
Aug 07 #Python
Python如何绘制日历图和热力图
Aug 07 #Python
Pycharm2020.1安装无法启动问题即设置中文插件的方法
Aug 07 #Python
手把手教你如何用Pycharm2020.1.1配置远程连接的详细步骤
Aug 07 #Python
Pycharm2020.1安装中文语言插件的详细教程(不需要汉化)
Aug 07 #Python
Pycharm 2020.1 版配置优化的详细教程
Aug 07 #Python
解决阿里云邮件发送不能使用25端口问题
Aug 07 #Python
You might like
php注入实例
2006/10/09 PHP
php不用正则验证真假身份证
2013/11/06 PHP
php中mkdir()函数的权限问题分析
2016/09/24 PHP
Laravel 解决composer相关操作提示php相关异常的问题
2019/10/23 PHP
jQuery EasyUI API 中文文档 - Draggable 可拖拽
2011/09/29 Javascript
jquery获取复选框被选中的值
2014/04/10 Javascript
javascript操作excel生成报表全攻略
2014/05/04 Javascript
jquery 表格排序、实时搜索表格内容(附图)
2014/05/19 Javascript
jQuery实现的输入框选择时间插件用法实例
2015/02/28 Javascript
JQuery中DOM事件冒泡实例分析
2015/06/13 Javascript
详细解读AngularJS中的表单验证编程
2015/06/19 Javascript
一些实用性较高的js方法
2016/04/19 Javascript
JS基于面向对象实现的拖拽功能示例
2016/12/20 Javascript
JQuery ZTree使用方法详解
2017/01/07 Javascript
vue element-ui table表格滚动加载方法
2018/03/02 Javascript
node.js之基础加密算法模块crypto详解
2018/09/11 Javascript
JS实现将对象转化为数组的方法分析
2019/01/21 Javascript
echarts大屏字体自适应的方法步骤
2019/07/12 Javascript
vue实现下拉加载其实没那么复杂
2019/08/13 Javascript
Python装饰器实现几类验证功能做法实例
2017/05/18 Python
python中logging包的使用总结
2018/02/28 Python
Flask框架通过Flask_login实现用户登录功能示例
2018/07/17 Python
python实现自动网页截图并裁剪图片
2018/07/30 Python
Python的Lambda函数用法详解
2019/09/03 Python
使用NumPy读取MNIST数据的实现代码示例
2019/11/20 Python
pandas实现DataFrame显示最大行列,不省略显示实例
2019/12/26 Python
python给图像加上mask,并提取mask区域实例
2020/01/19 Python
Keras自定义IOU方式
2020/06/10 Python
sklearn和keras的数据切分与交叉验证的实例详解
2020/06/19 Python
Python结合Window计划任务监测邮件的示例代码
2020/08/05 Python
python爬虫beautifulsoup解析html方法
2020/12/07 Python
html5录音功能实战示例
2019/03/25 HTML / CSS
Office DEPOT法国官网:欧迪办公用品采购
2018/01/03 全球购物
应用化学专业职业生涯规划书
2014/01/22 职场文书
村干部群众路线教育活动对照检查材料
2014/10/01 职场文书
解决pycharm下载库时出现Failed to install package的问题
2021/09/04 Python