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中的应用之translate和maketrans用法详解
Aug 27 Python
Python查找相似单词的方法
Mar 05 Python
在Python中处理列表之reverse()方法的使用教程
May 21 Python
Python中如何获取类属性的列表
Dec 26 Python
python机器学习库常用汇总
Nov 15 Python
深入理解python中sort()与sorted()的区别
Aug 29 Python
ubuntu16.04制作vim和python3的开发环境
Sep 23 Python
简单了解python高阶函数map/reduce
Jun 28 Python
python 返回一个列表中第二大的数方法
Jul 09 Python
Python django框架输入汉字,数字,字符生成二维码实现详解
Sep 24 Python
Python打包工具PyInstaller的安装与pycharm配置支持PyInstaller详细方法
Feb 27 Python
浅谈对python中if、elif、else的误解
Aug 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中get_object_vars()方法用法实例
2015/02/08 PHP
使用symfony命令创建项目的方法
2016/03/17 PHP
JavaScript字符串插入、删除、替换函数使用示例
2013/07/25 Javascript
更快的异步执行(setTimeout多浏览器)
2014/08/12 Javascript
基于ajax实现文件上传并显示进度条
2015/08/03 Javascript
黑帽seo劫持程序,js劫持搜索引擎代码
2015/09/15 Javascript
Node.js与Sails ~项目结构与Mvc实现及日志机制
2015/10/14 Javascript
jQuery插件开发精品教程让你的jQuery提升一个台阶
2016/01/27 Javascript
jQuery事件委托之Safari
2016/07/05 Javascript
JS实现图文并茂的tab选项卡效果示例【附demo源码下载】
2016/09/21 Javascript
jQuery插件HighCharts实现的2D对数饼图效果示例【附demo源码下载】
2017/03/09 Javascript
Angular2关于@angular/cli默认端口号配置的问题
2017/07/15 Javascript
微信小程序视图template模板引用的实例详解
2017/09/20 Javascript
nodejs基于express实现文件上传的方法
2018/03/19 NodeJs
还不懂递归?读完这篇文章保证你会懂
2018/07/29 Javascript
详解@Vue/Cli 3 Invalid Host header 错误解决办法
2019/01/02 Javascript
一篇文章介绍redux、react-redux、redux-saga总结
2019/05/23 Javascript
VueJS 取得 URL 参数值的方法
2019/07/19 Javascript
微信小程序全局变量的设置、使用、修改过程解析
2019/09/24 Javascript
bootstrap实现tab选项卡切换
2020/08/09 Javascript
Python获取DLL和EXE文件版本号的方法
2015/03/10 Python
Python标准库之collections包的使用教程
2017/04/27 Python
python3中的eval和exec的区别与联系
2019/10/10 Python
python实现KNN分类算法
2019/10/16 Python
利用python读取YUV文件 转RGB 8bit/10bit通用
2019/12/09 Python
加拿大女包品牌:Matt & Nat
2017/05/12 全球购物
在线课程:Skillshare
2019/04/02 全球购物
Ashford台湾:以折扣价提供奢华的男女用表款
2019/12/04 全球购物
Hibernate持久层技术
2013/12/16 面试题
社会实践活动总结报告
2014/04/29 职场文书
优秀语文教师事迹
2014/05/18 职场文书
会计毕业生自荐书
2014/06/12 职场文书
美术专业自荐信
2014/07/07 职场文书
政审证明材料
2015/06/19 职场文书
委托书范本格式
2019/04/18 职场文书
《天使的翅膀》读后感3篇
2019/12/20 职场文书