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内置的字符串处理函数整理
Jan 29 Python
python中关于时间和日期函数的常用计算总结(time和datatime)
Mar 08 Python
Python闭包实现计数器的方法
May 05 Python
简述Python中的进程、线程、协程
Mar 18 Python
PyTorch搭建多项式回归模型(三)
May 22 Python
Python中的list与tuple集合区别解析
Oct 12 Python
python 多维高斯分布数据生成方式
Dec 09 Python
python飞机大战pygame游戏之敌机出场实现方法详解
Dec 17 Python
pytorch中获取模型input/output shape实例
Dec 30 Python
Python爬虫工具requests-html使用解析
Apr 29 Python
Python通用唯一标识符uuid模块使用案例
Sep 10 Python
Pycharm中如何关掉python console
Oct 27 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数组键名技巧小结
2015/02/17 PHP
PHP中使用BigMap实例
2015/03/30 PHP
PHP7标量类型declare用法实例分析
2016/09/26 PHP
laravel model模型处理之修改查询或修改字段时的类型格式案例
2019/10/17 PHP
Json序列化和反序列化方法解析
2013/12/19 Javascript
深入理解JavaScript编程中的同步与异步机制
2015/06/24 Javascript
JavaScript中 ES6 generator数据类型详解
2016/08/11 Javascript
AngularJS模仿Form表单提交的实现代码
2016/12/08 Javascript
angularjs中回车键触发某一事件的方法
2017/04/24 Javascript
vue.js 初体验之Chrome 插件开发实录
2017/05/13 Javascript
Angular4表单验证代码详解
2017/09/03 Javascript
vue3.0 CLI - 3.2 路由的初级使用教程
2018/09/20 Javascript
JQuery中queue方法用法示例
2019/01/31 jQuery
vue ajax 拦截原理与实现方法示例
2019/11/29 Javascript
Python扫描IP段查看指定端口是否开放的方法
2015/06/09 Python
Python实现快速排序和插入排序算法及自定义排序的示例
2016/02/16 Python
Python实现将多个空格换为一个空格.md的方法
2018/12/20 Python
Python3 单行多行万能正则匹配方法
2019/01/07 Python
Python3解释器知识点总结
2019/02/19 Python
Django框架登录加上验证码校验实现验证功能示例
2019/05/23 Python
python实现批量视频分帧、保存视频帧
2019/05/31 Python
python实现ip地址查询经纬度定位详解
2019/08/30 Python
python3中sys.argv的实例用法
2020/04/24 Python
Python pip使用超时问题解决方案
2020/08/03 Python
安装Anaconda3及使用Jupyter的方法
2020/10/27 Python
意大利奢侈品多品牌集合店:TheDoubleF
2019/08/24 全球购物
自考毕业生自我鉴定
2013/11/04 职场文书
物理教师自荐信范文
2013/12/28 职场文书
小学生秋游活动方案
2014/02/23 职场文书
《忆江南》教学反思
2014/04/07 职场文书
领导干部遵守党的政治纪律情况思想汇报
2014/09/14 职场文书
学生会干部自我鉴定2014
2014/09/18 职场文书
师德自我剖析材料范文
2014/10/06 职场文书
实习单位鉴定意见
2015/06/04 职场文书
2016领导干部廉洁从政心得体会
2016/01/19 职场文书
CSS 还能这样玩?奇思妙想渐变的艺术
2021/04/27 HTML / CSS