上下文管理器是在Python 2.5加入的功能,什么是上下文管理器,Python’swithstatement supports the concept of a runtime contextdefined by a context manager.This is implemented using two separate methods
that allow user-defined classes to define a runtime context that is entered
before the statement body is executed and exited when the statement ends.这是文档中对它的解释。
所以,他的任务就是,在代码块执行前,做准备工作,在代码块执行完成后,做结束处理工作,也就是白话中的收尾。
他的优点不仅使代码的可读性更强并且减少了错误的几率。
我们自己也可以实现一个上下文管理器:
当然要实现一个上下文管理器,必须实现两个方法,一个__enter__方法,一个__exit__方法。
前者在进入代码块之前调用,后者在代码块执行完成后调用。
class ContextManagerDemo:
def __enter__(self):
print 'Entering the block'
def __exit__(self,type,value,traceback):
print 'Exiting the block'
with ContextManagerDemo():
print 'In the block'
#Output:
Entering the block
In the block
Exiting the block
这是一个非常简单的例子,那么异常处理放在哪里呢。
如果语句块发生了异常,__exit__方法就会被调用,而异常将会被重新raise。如果我们不想让异常被重新raise.也是有办法的,我们让__exit__方法返回True就可以阻止(不推荐)。
完备的__exit__方法名为:def __exit__(self,exc_type,exc_val,exc_tb) # (异常类型,异常值,异常追踪信息)
我们还可以使用装饰器和生成器来实现上下文管理器。python 有个contextlib模块可以提供更易用的上下文管理器。
1.contextmanager
from contextlib import contextmanager
@contextmanager
def tag(name):
print "<%s>" % name
yield
print "</%s>" % name
>>> with tag("h1"):
... print "foo"
...
output:
<h1>
foo
</h1>
2.nested
with contextlib.nested(open('fileToRead.txt', 'r'),open('fileToWrite.txt', 'w')) as (reader, writer):
writer.write(reader.read())
conetextlib.nested(..)方法有效地减少了嵌套
3.closing
from contextlib import closing
import urllib
with closing(urllib.urlopen('http://www.python.org')) as page:
for line in page:
print line
不需要明确的关闭Page.即使发生错误,当with 代码块退出时Page.close() 将被调用。