上下文管理器

  一直对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的更多相关文章

  1. Python 上下文管理器模块--contextlib

    在 Python 处理文件的时候我们使用 with 关键词来进行文件的资源关闭,但是并不是只有文件操作才能使用 with 语句.今天就让我们一起学习 Python 中的上下文管理 contextlib ...

  2. python上下文管理器细读

    test 1 上下文管理器,将生成器转化为上下文管理器 import contextlib @contextlib.contextmanager def a(): print(1) yield pri ...

  3. python上下文管理器ContextLib及with语句

    http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能 ...

  4. python 上下文管理器contextlib.ContextManager

    1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...

  5. Python上下文管理器

    在Python中让自己创建的函数.类.对象支持with语句,就实现了上线文管理协议.我们经常使用with open(file, "a+") as f:这样的语句,无需手动调用f.c ...

  6. Python上下文管理器 with

    对于系统资源的操作,如:文件操作.数据库操作等,我们往往打开文件.连接数据库后忘了将其close掉,这时就可能会引发异常,因此我们常用的做法是: # coding:utf-8 f = open(&qu ...

  7. Python上下文管理器(Context managers)

    上下文管理器(Context managers) 上下文管理器允许你在有需要的时候,精确地分配和释放资源. 使用上下文管理器最广泛的案例就是with语句了.想象下你有两个需要结对执行的相关操作,然后还 ...

  8. 吃透Python上下文管理器

    什么是上下文管理器? 我们常见的with open操作文件,就是一个上下文管理器.如: with open(file, 'rb') as f: text = f.read() 那上下文管理器具体的定义 ...

  9. Python上下文管理器你学会了吗?

    ​什么是上下文管理器 对于像文件操作.连接数据库等资源管理的操作,我们必须在使用完之后进行释放,不然就容易造成资源泄露.为了解决这个问题,Python的解决方式便是上下文管理器.上下文管理器能够帮助你 ...

随机推荐

  1. 【前端】JavaScript中prototype和__proto__的区别

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/prototype.html 经常有小伙伴问我关于prototype和__proto__的问题,觉得有必要写一篇博客 ...

  2. Jmeter_beanshell实现字符串加密

    Jmeter内置的没有MD5加密方法,所以需要写一些java代码实现加密功能,以下是具体操作: 1:用eclipse建个工程(包名.类名.方法名自己起) package com.wjika.test; ...

  3. php学习笔记之一维数组

    数组是指可以存放多个数据的数据类型. PHP中数组是一组关键字(key)和值(values)的集合,值可以是任何一种数据类型, 一维数组的创建方式: $arr=array(2,5,6); $arr=a ...

  4. Java获取当前的日期和时间

    Java获取当前的日期和时间 1.具体实现方法如下 /** * @Title:DateTime.java * @Package:com.you.model * @Description:获取当前的日期 ...

  5. free 或delete后指针怎么样了

    free()和delete()只是把指针所指向的内存释放掉,但是并没有把指针本身删除,也没有把指针置为NULL; #include<iostream> using namespace st ...

  6. 各种HTML锚点跳转方式

    1 js控制锚点跳转 <a name="anchor"></a> location.hash="anchor"; 不只有a其他元素也可以 ...

  7. C# 找出泛型集合中的满足一定条件的元素 List.Wher()

    在学习的过程中,发现泛型集合List<T>有一个Where函数可以筛选出满足一定条件的元素,结合Lambda表达式使用特别方便,写出来与大家分享. 1.关于Func<> Fun ...

  8. eclipse远程调试Tomcat方法(测试成功并且说说遇到的坑)

    转自:http://blog.csdn.net/afgasdg/article/details/9236877 PS:文中容易引起歧义的地方已经做了修改:另外,本人参照以下步骤操作,结果无法调试,后来 ...

  9. ajax面试题

    1.ajax是什么?如何创建一个ajax? ajax并不算是一种新的技术,全称是asynchronous javasript and xml,可以说是已有技术的组合,主要用来实现客户端服务器的异步通信 ...

  10. tomcat启动很慢很慢很慢

    今天下载tomcat8.5,启动的时候发现非常慢,大概三分钟左右才能启动,网上搜到一个解决方案,在此记录下来 原因: Tomcat 7/8都使用org.apache.catalina.util.Ses ...