在Python中让自己创建的函数、类、对象支持with语句,就实现了上线文管理协议。我们经常使用with open(file, “a+”) as f:这样的语句,无需手动调用f.close()关闭文件。这种用法不仅优雅,而且避免遗忘释放资源,十分方便。所以,当操作某些资源时,需要对资源的获取与释放进行自动操作,就可以用上线文管理器。比如:数据库的连接,查询,关闭处理;socket的连接和断开。本篇主要介绍,如何让自己创建的类、对象、函数等支持with语句,详细请看下文。

1 让对象支持上下文管理协议

在类中,实现__enter__()__exit__()方法,类创建的对象就支持with语句。如下:

class A:def __enter__(self):print("in __enter__")return [1, 2, 3]def __exit__(self, exc_type, exc_val, exc_tb):print("in __exit__")obj = A()
with obj as o:print("看看o是什么:", o)print("do something")
print("end")  

注意本例的输出结果的顺序:

in __enter__
看看o是什么: [1, 2, 3]
do something
in __exit__
end

(1)当执行 with 语句的时候,对象的 __enter__()方法被触发, 它返回的值(如果有的话)会被赋值给 as 声明的变量。对应输出应该是in __enter__和将[1,2,3]赋值给o字母o

(2)然后,with 语句块里面的代码开始执行。对应的输出是看看o是什么: [1, 2, 3]do someting

(3)最后,__exit__()方法被触发进行清理工作。对应的输出是in __exit__

补充说明:
__exit__()方法的第三个参数包含了异常类型、异常值和追溯信息(如果有的话)。__exit__()方法能自己决定怎样利用这个异常信息,或者忽略它并返回一个None值。

如果 __exit__() 返回 True ,那么异常会被清空,就好像什么都没发生一样, with 语句后面的程序继续在正常执行。

上面的例子还不支持多个with嵌套使用,下面是一个可以嵌套使用with语句的例子:

'''
学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
from socket import socket, AF_INET, SOCK_STREAMclass Connection:def __init__(self, address, family=AF_INET, type=SOCK_STREAM):self.address = addressself.family = familyself.type = typeself.connections = []def __enter__(self):sock = socket(self.family, self.type)sock.connect(self.address)self.connections.append(sock)return sockdef __exit__(self, exc_ty, exc_val, tb):self.connections.pop().close()conn = Connection(('www.python.org', 80))
with conn as s1:print(s1)with conn as s2:print(s2)

2 装饰器版上下文管理器

上面介绍了在类和对象中实现上下文管理协议,其实Python标准库中contextlib包的@contextmanager装饰器能够轻松实现一个上下文管理器,下例是用其实现统计代码块耗时的上下文管理器:

import time
from contextlib import contextmanager
# 来看一个装饰器版本的上下文管理器
# 检查代码消耗时间块
@contextmanager
def timecount(name):start = time.time()try:yieldfinally:end = time.time()print('{}: {}'.format(name, end - start))with timecount('cost time:'):time.sleep(2)
# cost time:: 2.000200033187866

timecount()中,yield之前的代码相当于__enter__()方法;yield 之后的代码相当于 __exit__()方法。如果有异常会自动在yield一行抛出。

上下文管理器可以应用在事务中:

'''
学习中遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
# 更高级的事务管理
@contextmanager
def list_transaction(orig_list):working = list(orig_list)yield workingorig_list[:] = workinglis = [1, 2, 3]
with list_transaction(lis) as work:work.append(5)work.append(6)print(lis)
# [1, 2, 3, 5, 6]  

一旦with语句内有异常产生,之前的操作不会生效:

lis = [1, 2, 3]
with list_transaction(lis) as work:work.append(5)work.append(6)print(lis)raise RuntimeError("回滚")  

如果在交互式命令行中打印lis,依然会发现lis的内容没有改变,也就是说,with语句中的代码出现异常,with语句中的操作都不会生效,只有with无异常退出,才会生效。对于事务管理来说是比较有用的。

3 总结

(1)当操作一些需要打开、连接、断开或释放的资源时,让对象或函数支持with语句十分方便、省事、优雅。如数据库的链接断开、套接字的连接断开、事务、锁资源等。

(2)类中实现__enter__()__exit__()方法,即可实现上下文管理协议,对象可使用with语句。

(3)通过contextlib包中的@contextmanager装饰器装饰一个函数,该函数即可使用with语句。

Python中必须知道的知识点:上下文管理器相关推荐

  1. python的上下文管理用哪个关键字_正确理解python中的关键字“with”与上下文管理器...

    正确理解python中的关键字"with"与上下文管理器 来源:中文源码网    浏览: 次    日期:2018年9月2日 [下载文档:  正确理解python中的关键字&quo ...

  2. [转载] 玩转python中with的使用与上下文管理器

    参考链接: Python中的上下文管理器 人是随着时间不断进化而来的,同样编程语言也是随着IT行业的更新换代,功能模块不断地优化与丰富才壮大起来的.比如在python2.5之前使用open读写文件操作 ...

  3. python中with的用法,上下文管理器

    一.上下文管理器 含有__enter__和__exit__方法的对象就是上下文管理器 class Foo(object):def __init__(self):print('实例化一个对象')def ...

  4. Python 上下文管理器和 with 语句

    1. 上下文管理器概念 什么是 Python 的上下文管理器(Context Managers)呢? ​ 含有 __enter__ 和 __exit__ 方法的对象就是.上下文管理器存在的目的是管理 ...

  5. python语言使用什么语句实现上下文管理协议_Python 技巧探究:上下文管理器和with语句...

    一:前言 Python 里面的 with 语句是被认为是晦涩难懂的特征之一,但是当你窥视它的内部你就会发现这里面并没有什么魔法.事实上它可以帮助我们写一些整洁和可读性高的代码. 那么 with 语句适 ...

  6. Python基础教程:上下文管理器 context manager(with...as...)

    一.概念 上下文管理器:就是实现了上下文管理协议的对象.主要用于保存和恢复各种全局状态,关闭文件等.上下文管理器本身是一种装饰器. 上下文允许可以自动的开始和结束一些和事情.例如当利用with-as打 ...

  7. Python 上下文管理器与with语句

    Python中把进入代码块前调用__enter__ 方法并在离开代码块后调用__exit__方法的对象作为上下文管理器,本文中我们就来深入解析Python中的上下文管理器,来看看上下文管理器的作用及用 ...

  8. 深入理解 Python 中的上下文管理器

    图|李思瑶 文|MING 提示:前面的内容较为基础,重点知识在后半段. with 这个关键字,对于每一学习Python的人,都不会陌生. 操作文本对象的时候,几乎所有的人都会让我们要用 with op ...

  9. python上下文管理关键字_详解 Python 中的 with 与 上下文管理器

    with 这个关键字,对于每一学习Python的人,都不会陌生. 操作文本对象的时候,几乎所有的人都会让我们要用 with open ,这就是一个上下文管理的例子.你一定已经相当熟悉了,我就不再废话了 ...

最新文章

  1. Nature封面:每天工作21.5小时的AI化学家,8天内完成688个实验,已自主发现一种全新催化剂...
  2. javascript的变量
  3. 12新特性格式化输出f-string
  4. 数据结构行编辑成簇 c语言,索引的数据结构及底层存储
  5. jquery笔记一:下载安装、语法、选择器、遍历选择元素的方法、jQuery动画
  6. Java入门知识,写一个最简单java程序
  7. Hive_Hive的数据模型_视图
  8. ssh免密码远程执行sudo命令
  9. Linux网络子系统中协议栈的入口处理
  10. 二维数组求最大子数组和
  11. vb杨辉三角代码编写_杨辉三角怎样用VB写杨辉三角的完整代码 – 手机爱问
  12. 心电图 python_能测血压,还有心电图,兼顾9大运动模式,dido手环还不错
  13. 运动控制+机器视觉Demo软件框架系统概述
  14. iOS大神牛人的博客集合
  15. 大江大河未来10年:中国人改变命运的的七次机遇
  16. 文章推荐列表(个人收藏)
  17. java.net.SocketException: Too many open files解决方法
  18. php 中文拼音模糊查询,PHP-输入字母 模糊查询汉字
  19. YC全球总裁:我招揽陆奇好多年,如今终于如愿了!
  20. 计算机人脸识别算哪个专业,人脸识别属于计算机什么领域

热门文章

  1. 基于PHP7的提供数据管理工具框架Meloy 1.0.3 发布
  2. 提升购物体验,跨境电商如何做企业管理?
  3. 我的Spring 之旅---Spring实战
  4. 使用牛刀云开发微信小程序(问题集锦)
  5. 关于Netty的一些理解、实践与陷阱
  6. [转]ActionScript 3.0入门:Hello World、文件读写、数据存储(SharedObject)、与JS互调
  7. 【转】Java 内存模型及GC原理
  8. pro mvvm 读书笔记
  9. Web ReplayType?
  10. rog live service是什么_王者荣耀日活跃用户破亿!ROG游戏手机助力水友赛进入4强争夺...