python 小知识 - 什么是上下文管理
python 中进行文件操作,经常被建议使用with open
的方式,形如:
why? 这背后的原因是什么?
直观的解释是:这样的好处文件操作是 io 操作,操作完成之后,需要关闭 close,避免文件一直被占用打开。
与之对比另一种写法是:
两种写法对比可以知道:with 方式隐式的帮我们做了资源的释放操作,而这个可能是我们可能遗忘的。
那 with 是什么?有没有其他的作用?就是今天的主题。
1.with 上下文管理
with 是一种 python 上下文管理方式;什么是上下文(context)
context 是指程序运行所处于的环境和自身的状态(如数据)
比如上面提到的文件操作,包含了文件打开获取文件操作的句柄权限(获得资源)、处理文件信息、关闭文件(释放资源);这些都是可以认为是文件的操作的环境和状态,也就是一个上下文(context 上下文这个译文有点怪怪,可以理解成一个容器内操作一个过程)
所以 with 上下文管理就是用在某种资源的创建,使用和回收以及异常处理过程中。语法结构如下:
结合文件操作来说:
context_expression:获取资源,获取文件流
as target(s): 是可选的,可以认为资源变量
with-body: 具体的文件操作
2.如何构建自己的上下文管理
with 内部是如何实现的? 从上下文管理的概念可以知道:一个是获取资源,一个是释放资源。
与之对应的,只要实现了下面两个协议的都可以用 with 来进行上下文管理
enter: 实现获取资源
exit: 来实现释放资源的操作
我们来看下具体的例子:
可以看出 __exit__
包含了with-body
的异常控制的处理和捕捉,返回 TRUE 表示程序已经捕获到异常并处理。所以即使你在函数with_body
中出现异常情况,程序也会正常执行,除非你在__exit__
直接抛出异常。
可以还原下 open 的写法:
3.用 contextlib 简化
对于需要上下文管理的场景,都要建立一个类,并实现 enter 和 __exit__接口来实现上下文管理;有没有更好的方式。
python 提供 contextlib 装饰器来简化上下文管理,具体如下:
可以看出,
contextlib.contextmanager
通过 yield 来代表资源,yield 前面的获取资源
通过 try...except 来进行异常处理,通过 finally 来做资源释放
版权声明: 本文为 InfoQ 作者【AIWeker】的原创文章。
原文链接:【http://xie.infoq.cn/article/a71c5570aa8132262a0b4c670】。文章转载请联系作者。
评论