Python实现上下文管理器的方法
作者:David Beazley 发布时间:2021-06-22 17:31:15
标签:Python,上下文管理器
问题
你想自己去实现一个新的上下文管理器,以便使用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__()
方法。
来源:https://python3-cookbook.readthedocs.io/zh_CN/latest/c09/p22_define_context_managers_the_easy_way.html


猜你喜欢
- 输入字母验证码,俺觉得特烦,特别还要输入大写字母。于是找到文件并修改成数字验证码。 修改文件 验证码文件位置 include\va
- 集合数据类型的添加操作在 “redis-py” 中也是通过 “sadd&
- 如下所示:<select id="host_list" name="host_list" mu
- 一、概述推荐使用参考网站: json在python中,json模块可以实现json数据的序列化和反序列化序列化:将可存放在内存中的pytho
- 当我们提到一门编程语言的效率时:通常有两层意思,第一是开发效率,这是对程序员而言,完成编码所需要的时间;另一个是运行效率,这是对计算机而言,
- 简介:pycharm 是一款功能强大的 Python 编辑器,具有跨平台性。下载地址第一步:下载pycharm 软件下载时会有两个版本供选择
- 排序这个词,我的第一感觉是几乎所有App都有排序的地方,淘宝商品有按照购买时间的排序、B站的评论有按照热度排序的...对于MySQL,一说到
- 本博文的知识点一个是模块的调用和一个自定义函数返回值赋值给变量编写一个简单的函数模块:[root@bigdata zw]# more d.p
- 总的来讲,JavaSever PagesTM(JSP)和 微软的Active Sever Pages(ASP)在技术方面有许多相似之处。两者
- 首先我们知道这个效果应该是一个老话题了。今天整理文件的时候,发现自己以前的一些布局的解决方法躺在文件夹里很长时间了,翻翻老底吧。需要说明的是
- 本文实例讲述了python集合的创建、添加及删除操作。分享给大家供大家参考,具体如下:集合时无序可变的序列,集合中的元素放在{}内,集合中的
- 在asp代码中分页是有点麻烦的事情,个人在在代码编写过程中把分页代码写成了两个函数,虽然在功能上不是很完善,但对于一般的应用应该是满足的了。
- 验证码制作#string模块自带数字、字母、特殊字符变量集合,不需要我们手写集合import stringimport randomimpo
- 本文介绍了python技能之导出excel的实例代码,正好能用到,写出来分享给大家作为一个数据分析师,下面的需求是经常会遇到的。从数据库或者
- 在python中,文件使用十分频繁,本文将向大家介绍python文件路径的操作:得到指定文件路径、得到当前文件名、判断文件路径是否存在、获得
- 引言项目中有一个需求:需要根据学期时间动态的计算出该学期有多少周通过上网查找,找到了一个工具类moment.jsmoment.js是一个Ja
- 本文实例讲述了MySQL游标概念与用法。分享给大家供大家参考,具体如下:1、游标的概念(Cursor)一条sql,对应N条资源,取出资源的接
- 认识pip众所周知,pip可以对python的第三方库进行安装、更新、卸载等操作,十分方便。pip的全称:package installer
- 本文实例讲述了JS小游戏的仙剑翻牌源码,是一款非常优秀的游戏源码。分享给大家供大家参考。具体如下:一、游戏介绍:这是一个翻牌配对游戏,共十关
- 学习目标1.掌握pytorch模型转换到onnx模型2.顺利运行onnx模型3.比对onnx模型和pytorch模型的输出结果学习大纲pyt