【Python】 上下文管理器和contextlib
上下文管理器
一直对python中的上下文管理比较迷惑,趁着今天研究SQLAlchemy顺便看了一下,感觉稍微清楚了一点。http://www.cnblogs.com/chenny7/p/4213447.html参考了这篇文章。
所谓上下文,在函数式编程这个具体的场景中来说,可以理解为和闭包有些类似的一种东西。比如在闭包和装饰器那篇文章中我提到过利用自定义一个装饰器来得到一个加强版的函数。为什么它能够得到加强,就是因为在执行这个函数时,解释器会自动执行一些装饰器中定义的操作。而回到上下文这个话题,很常见的一个例子就是用with语句来打开文件:
with open("test.txt","w") as fi:
fi.write("hello,world")
相比于传统的文件读写方式,利用with语句来管理上下文的方法做这件事更加省心,我们不用手动地fi.close()了,当with语句块中执行出错也不要紧,fi还是会被close的。那么with语句到底干了点什么事?
在回答这个问题之前,首先要明确with语句后面跟的对象并不是什么都行,这个对象应该要能支持上下文管理协议。换言之,这个对象应该实现了上下文管理器。就像我们说一个对象是迭代器的话就是说它实现了__iter__方法和next方法一样,可以在with后面正常工作的对象需要实现了__enter__以及__exit__方法。
这两个方法顾名思义,就是分别指在进入with语句执行之前和结束with语句块执行之后执行的一些操作。基于这样的一种想法,我们就可以自己创建一个可以和with语句配合工作的对象了。比如:
class A:
def __enter__(self):
print '__enter__() called' def __exit__(self, e_t, e_v, t_b):
print '__exit__() called' with A() as a:
print('got instance') ####得到结果####
#__enter__() called
#got instance
#__exit__() called
值得注意的是__exit__()方法有三个参数,当with语句块中所有语句都正常结束没有出现错误或者异常时这三个参数都是None地进入__exit__方法,但是如果出错了,那么这三个参数就依次是sys.exc_info()得到的三个值,分别是异常类(exc_type)、异常实例(exc_value)和跟踪记录(traceback)。
■ 关于contextlib
有时候我们仅仅需要一个针对函数的上下文管理器,并不想写一个新类来实现上下文的管理,这时候可以用contextlib这个内建的库。与其说是一个库,其实我们主要用了这个库中的contextmanager这个装饰器函数:
from contextlib import contextmanager @contextmanager
def context():
print 'entering the zone'
try:
yield
print "after with"
except Exception, e:
print 'with an error %s'%e
raise e
else:
print 'with no error' with context() as c:
print c
print '----in with call------'
在import 了 contextmanager之后,用@contextmanager的方式来把我们的函数装饰起来。我们的函数(在这里当然就是context())应该是一个生成器函数,再接受装饰之后它就可以被放到with语句后面,作为一个上下文管理器来管理with语句块中的语句。
执行顺序是这样的:首先进入context函数开始执行,直至碰到第一个yield语句,把yield得到的对象返回赋值给value变量。然后开始执行with语句块中的语句,执行完成之后,回到context函数中yield的位置继续向下执行。如果在执行with语句块的时候出现了任何异常,那么异常会被传递到context中的except语句块中进行异常处理。
所以,上述代码执行的结果是:
entering the zone
None
----in with call------
after with
with no error
【Python】 上下文管理器和contextlib的更多相关文章
- Python 上下文管理器模块--contextlib
在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...
- python上下文管理器细读
test 1 上下文管理器,将生成器转化为上下文管理器 import contextlib @contextlib.contextmanager def a(): print(1) yield pri ...
- python上下文管理器ContextLib及with语句
http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能 ...
- python 上下文管理器contextlib.ContextManager
1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...
- Python上下文管理器
在Python中让自己创建的函数.类.对象支持with语句,就实现了上线文管理协议.我们经常使用with open(file, "a+") as f:这样的语句,无需手动调用f.c ...
- Python上下文管理器 with
对于系统资源的操作,如:文件操作.数据库操作等,我们往往打开文件.连接数据库后忘了将其close掉,这时就可能会引发异常,因此我们常用的做法是: # coding:utf-8 f = open(&qu ...
- Python上下文管理器(Context managers)
上下文管理器(Context managers) 上下文管理器允许你在有需要的时候,精确地分配和释放资源. 使用上下文管理器最广泛的案例就是with语句了.想象下你有两个需要结对执行的相关操作,然后还 ...
- 吃透Python上下文管理器
什么是上下文管理器? 我们常见的with open操作文件,就是一个上下文管理器.如: with open(file, 'rb') as f: text = f.read() 那上下文管理器具体的定义 ...
- Python上下文管理器你学会了吗?
什么是上下文管理器 对于像文件操作.连接数据库等资源管理的操作,我们必须在使用完之后进行释放,不然就容易造成资源泄露.为了解决这个问题,Python的解决方式便是上下文管理器.上下文管理器能够帮助你 ...
随机推荐
- HighCharts之2D堆面积图
HighCharts之2D堆面积图 1.HighCharts之2D堆面积图源码 StackedArea.html: <!DOCTYPE html> <html> <hea ...
- JavaScript向select下拉框中添加和删除元素
JavaScript向select下拉框中添加和删除元素 1.说明 a 利用append()方法向下拉框中添加元素 b 利用remove()方法移除下拉框中最后一个元素 2.设计源码 < ...
- Linux显示系统的诊断信息
Linux显示系统的诊断信息 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ dmesg [ 1.492480] EDD information not ava ...
- C# GUID介绍和的使用
GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成GUID的API.生成算法很有意思,用到了以太网卡地址.纳秒级时间.芯片ID码和许多可 ...
- 三十天学不会TCP,UDP/IP网络编程 - 绅士的开始
经过了过年的忙碌和年初的懈怠一切的日子,我又开始重新更新了~这是最新的一篇~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到. 如果对和程序员有关 ...
- python 实现多层目录文件查找
本文针对多层目录下文件的查找. 利用 os模块的基本操作,并利用递归的思想实现了目录多层查找. 代码如下: import os #dir_name: 处理文件的起始目录 def count_file( ...
- 8.C++-类的关键字
在之前学习的C++章节里,可以发现结构体越来越不像C语言里的结构体了 比如,里面可以定义函数,可以定义private/public,结构体名还可以指向父类. 但是C++需要兼容C,所以C++中便提供了 ...
- 关于spring事务注解实战
1.概述 spring的事务注解@Transaction 相信很多人都用过,而@Transaction 默认配置适合80%的配置. 本篇文章不是对spring注解事务做详细介绍,而是解决一些实际场景下 ...
- GridView添加事件监听和常用属性解析
1. 使用流程 graph LR 准备数据源-->新建适配器 新建适配器-->绑定数据源 绑定数据源-->加载适配器 2. 常用属性 android:columnWidth:每一列的 ...
- ListView添加item的事件监听
1. 点击事件(OnItemClickListener) onItemClick(AdapterView<?> parent, View view, int position, long ...