上下文管理器

  一直对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. win8.1中安装rabbitmq

    项目测试的时候,用的是项目组linux测试机上的rabbitmq,为了方便自己随时使用,便在自己的电脑win8.1上也安装了一套,安装过程如下: 一.准备erlang和rabbitmq的安装程序:   ...

  2. error: No curses/termcap library found的解决办法

    mysql版本:5.1.30 已经不记得这次是第几次安装mysql了,遇到这个问题倒是第一次. 之前在tar,./configure,make,make install 经典四步时,从来没有想过其中的 ...

  3. R语言︱逻辑运算

    R软件包含两个逻辑值,TRUE和FALSE.在其他编程语言中也称为布尔值(Boolean values).布尔向量就是充满着逻辑值的逻辑向量.那么有如何的应用呢? 1.比较运算可以产生逻辑值  > ...

  4. ASP.NET Core 2.0 : 六. 举个例子来聊聊它的依赖注入

    本文通过一个维修工与工具库的例子形象的描述一下为什么要用依赖注入.它的工作原理是什么样的, 然后根据这个类比一下ASP.NET Core 中的依赖注入, 从而深刻了解它的使用方法.注意事项以及回收机制 ...

  5. 小实验3:实现haproxy的增、删、查

    # Author:Alano # -*- conding:utf-8 -*- # 这里有一个问题:为什么手动删除了haproxy_new中的内容,但是执行添加命令的时候依然显示数据已经存在? f = ...

  6. Git Compare with base,比较大文件时,长时间等待,无法加载

    问题 当使用Git比较一个大文件(几十兆数量级)版本见差异时,会一直等待加载,且内存消耗很大,导致其他进程很难执行.任务管理器中,可以看到此时的TortoiseGitMerge吃掉3G左右的内存. 原 ...

  7. newInstance 与new的区别

    用newInstance与new的区别? 区别在于创建对象的方式不一样,前者是使用类加载机制,后者new 的类可以没有加载: 使用newInstance时候,必须保证:1.这个类已加载,2.这个类已经 ...

  8. 你该怎么选Offer

    原文出处:http://www.360doc.com/content/15/1223/07/1209677_522436084.shtml 记录目的:自勉.分享 摘要 一段时间无数公司.无数投资人蜂拥 ...

  9. Entity Framework 乐观并发处理

    Entity Framework 乐观并发处理 有一段时间没有更新博客了,今天终于有一些时间,和大家讨论一个Entity Framework 乐观并发处理的问题.首先需要说明的是,这里提到的 “并发” ...

  10. 【Spring源码分析】.properties文件读取及占位符${...}替换源码解析

    前言 我们在开发中常遇到一种场景,Bean里面有一些参数是比较固定的,这种时候通常会采用配置的方式,将这些参数配置在.properties文件中,然后在Bean实例化的时候通过Spring将这些.pr ...