python2.7高级编程 笔记一(Python中的with语句与上下文管理器学习总结)
0、关于上下文管理器
上下文管理器是可以在with语句中使用,拥有__enter__和__exit__方法的对象。
with manager as var:
do_something(var)
相当于以下情况的简化:
var = manager.__enter__()
try:
do_something(var)
finally:
manager.__exit__()
换言之,PEP 343中定义的上下文管理器协议允许将无聊的try...except...finally结构抽象到一个单独的类中,仅仅留下关注的do_something部分。
__enter__方法首先被调用。它可以返回赋给var的值。as部分是可选的:如果它不出现,enter的返回值简单地被忽略。
with语句下的代码被执行。就像try子句,它们或者成功执行到底,或者break,continue或return,或者可以抛出异常。无论哪种情况,该块结束后,__exit__方法被调用。如果抛出异常,异常信息被传递给__exit__,这将在下一章节讨论。通常情况下,异常可被忽略,就像在finally子句中一样,并且将在__exit__结束后重新抛出。
比如说我们想确认一个文件在完成写操作之后被立即关闭:
>>> class closing(object):
... def __init__(self, obj):
... self.obj = obj
... def __enter__(self):
... return self.obj
... def __exit__(self, *args):
... self.obj.close()
>>> with closing(open('/tmp/file', 'w')) as f:
... f.write('the contents\n')
这里我们确保了当with块退出时调用了f.close()。因为关闭文件是非常常见的操作,该支持已经出现在file类之中。它有一个__exit__方法调用close,并且本身可作为上下文管理器。
>>> with open('/tmp/file', 'a') as f:
... f.write('more contents\n')
try...finally常见的用法是释放资源。各种不同的情况实现相似:在__enter__阶段资源被获得,在__exit__阶段释放,如果抛出异常也被传递。正如文件操作,往往这是对象使用后的自然操作,内置支持使之很方便。每一个版本,Python都在更多的地方提供支持。
1、如何使用上下文管理器:
如何打开一个文件,并写入"hello world"
filename="my.txt"
mode="w"
writer=open(filename,mode)
writer.write("hello world")
writer.close()
当发生异常时(如磁盘写满),就没有机会执行第5行。当然,我们可以采用try-finally语句块进行包装:
writer=open(filename,mode)
try:
writer.write("hello world")
finally:
writer.close()
当我们进行复杂的操作时,try-finally语句就会变得丑陋,采用with语句重写:
with open(filename,mode) as writer:
writer.write("hello world")
as指代了从open()函数返回的内容,并把它赋给了新值。with完成了try-finally的任务。
2、自定义上下文管理器
with语句的作用类似于try-finally,提供一种上下文机制。要应用with语句的类,其内部必须提供两个内置函数__enter__和__exit__。前者在主体代码执行前执行,后者在主体代码执行后执行。as后面的变量,是在__enter__函数中返回的。
class echo():
def output(self):
print "hello world"
def __enter__(self):
print "enter"
return self #可以返回任何希望返回的东西
def __exit__(self,exception_type,value,trackback):
print "exit"
if exception_type==ValueError:
return True
else:
return Flase >>>with echo as e:
e.output()
enter
hello world
exit
完备的__exit__函数如下:
def __exit__(self,exc_type,exc_value,exc_tb)
其中,exc_type:异常类型;exc_value:异常值;exc_tb:异常追踪信息
当__exit__返回True时,异常不传播
3、contextlib模块
contextlib模块的作用是提供更易用的上下文管理器,它是通过Generator实现的。contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制,常用框架如下:
from contextlib import contextmanager
@contextmanager
def make_context():
print 'enter'
try:
yield "ok"
except RuntimeError,err:
print 'error',err
finally:
print 'exit' >>>with make_context() as value:
print value
输出为:
enter
ok
exit
其中,yield写入try-finally中是为了保证异常安全(能处理异常)as后的变量的值是由yield返回。yield前面的语句可看作代码块执行前操作,yield之后的操作可以看作在__exit__函数中的操作。
以线程锁为例:
@contextlib.contextmanager
def loudLock():
print 'Locking'
lock.acquire()
yield
print 'Releasing'
lock.release() with loudLock():
print 'Lock is locked: %s' % lock.locked()
print 'Doing something that needs locking' #Output:
#Locking
#Lock is locked: True
#Doing something that needs locking
#Releasing
4、contextlib.nested:减少嵌套
对于:
with open(filename,mode) as reader:
with open(filename1,mode1) as writer:
writer.write(reader.read())
可以通过contextlib.nested进行简化:
with contextlib.nested(open(filename,mode),open(filename1,mode1)) as (reader,writer):
writer.write(reader.read())
在python 2.7及以后,被一种新的语法取代:
with open(filename,mode) as reader,open(filename1,mode1) as writer:
writer.write(reader.read())
5、contextlib.closing()
file类直接支持上下文管理器API,但有些表示打开句柄的对象并不支持,如urllib.urlopen()返回的对象。还有些遗留类,使用close()方法而不支持上下文管理器API。为了确保关闭句柄,需要使用closing()为它创建一个上下文管理器(调用类的close方法)。
import contextlib
class myclass():
def __init__(self):
print '__init__'
def close(self):
print 'close()' with contextlib.closing(myclass()):
print 'ok'
输出:
__init__
ok
close()
python2.7高级编程 笔记一(Python中的with语句与上下文管理器学习总结)的更多相关文章
- Python中的with语句(上下文管理协议)
在平时工作中总会有这样的任务,它们需要开始前做准备,然后做任务,然后收尾清理....比如读取文件,需要先打开,读取,关闭 这个时候就可以使用with简化代码,很方便 1.没有用with语句 f = o ...
- python之with语句结合上下文管理器
所谓上下文管理器即在一个类中重写了__enter__方法和__exit__方法的类就可以成为上下文管理器类. 我们可以通过with语句结合上下文管理器简化一些操作. 使用with语句结合自定义上下文管 ...
- 【Python学习笔记】with语句与上下文管理器
with语句 上下文管理器 contextlib模块 参考引用 with语句 with语句时在Python2.6中出现的新语句.在Python2.6以前,要正确的处理涉及到异常的资源管理时,需要使用t ...
- python2.7高级编程 笔记二(Python中的描述符)
Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些" ...
- python之小记with open...as..上下文管理器
之前在学习file文件对象是说过,open文件操作结束后要关闭文件,否则会一直占用资源.但是当出现异常,如读取过程中文件不存在或异常,则直接出现错误,close方法无法执行,文件无法关闭 with o ...
- 『流畅的Python』第15章:上下文管理器和else块
- Python中的上下文管理器和with语句
Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于规定某个对象的使用范围.本文是针对于该功能的思考总结. 为什么需要上下文管理器? 首先, ...
- (转)Python中的上下文管理器和Tornado对其的巧妙应用
原文:https://www.binss.me/blog/the-context-manager-of-python-and-the-applications-in-tornado/ 上下文是什么? ...
- 深入理解 Python 中的上下文管理器
提示:前面的内容较为基础,重点知识在后半段. with 这个关键字,对于每一学习Python的人,都不会陌生. 操作文本对象的时候,几乎所有的人都会让我们要用 with open ,这就是一个上下文管 ...
随机推荐
- 【NLP】基于机器学习角度谈谈CRF(三)
基于机器学习角度谈谈CRF 作者:白宁超 2016年8月3日08:39:14 [摘要]:条件随机场用于序列标注,数据分割等自然语言处理中,表现出很好的效果.在中文分词.中文人名识别和歧义消解等任务中都 ...
- 史上最全、JavaScript基础篇
本章内容: 简介 定义 注释 引入文件 变量 运算符 算术运算符 比较运算符 逻辑运算符 数据类型 数字 字符串 布尔类型 数组 Math 语句 条件语句(if.switch) 循环语句(for.fo ...
- 谈谈枚举的新用法——java
问题的由来 前段时间改游戏buff功能,干了一件愚蠢的事情,那就是把枚举和运算集合在一起,然后运行一段时间后buff就出现各种问题,我当时懵逼了! 事情是这样的,做过游戏的都知道,buff,需要分类型 ...
- 『.NET Core CLI工具文档』(七)dotnet-new
说明:本文是个人翻译文章,由于个人水平有限,有不对的地方请大家帮忙更正. 原文:dotnet-new 翻译:dotnet-new 名称 dotnet-new -- 创建一个新的 .NET Core 项 ...
- C#——字段和属性
//我的C#是跟着猛哥(刘铁猛)(算是我的正式老师)<C#语言入门详解>学习的,微信上猛哥也给我讲解了一些不懂得地方,对于我来说简直是一笔巨额财富,难得良师! 在刚开始学习属性这一节时,开 ...
- C#调用SendMessage 用法
函数功能:该函数将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回.该函数是应用程序和应用程序之间进行消息传递的主要手段之一. 函数原型:LRESUL ...
- bzoj2693--莫比乌斯反演+积性函数线性筛
推导: 设d=gcd(i,j) 利用莫比乌斯函数的性质 令sum(x,y)=(x*(x+1)/2)*(y*(y+1)/2) 令T=d*t 设f(T)= T可以分块.又由于μ是积性函数,积性函数的约束和 ...
- Python input 使用
Python 3.0 中使用"input" , Python 2.0 中使用"raw_input"Python 3.5: #!C:\Program Files\ ...
- 开源跨平台IOT通讯框架ServerSuperIO,集成到NuGet程序包管理器,以及Demo使用说明
物联网涉及到各种设备.各种传感器.各种数据源.各种协议,并且很难统一,那么就要有一个结构性的框架解决这些问题.SSIO就是根据时代发展的阶段和现实实际情况的结合产物. 各种数据信息,如下图 ...
- SpringMVC + Spring + MyBatis 整合 + Spring shrio + easyUI + 权限管理框架,带shrio session和shrio cache集群实现方案
工作之余先来写了一个不算规范的简单架子 基于spring mvc + spring + mybatis + Spring shrio 基于redis的集群方案 系统权限部分,分成多个机构,其中每个机构 ...