赞
踩
提供函数:
**contextlib.contextmanager(func):**这个函数是一个装饰器,能够用于去定义一个生产函数给with语句上下文管理者,不需要创建类或者各自的__enter__() 和__exit__()方法。
然而很多对象对于使用with语句的有与生俱来支持,有时需要管理的资源本身并不是上下文管理器,并且没有实现用于context . closing的close()方法。
一个抽象的例子是之后保证正确的资源管理:
from contextlib import contextmanager
@contextmanager #修饰
def managed_resource(*args, **kwds):
# Code to acquire resource, e.g.:
resource = acquire_resource(*args, **kwds)
try:
yield resource
finally:
# Code to release resource, e.g.:
release_resource(resource)
>>> with managed_resource(timeout=3600) as resource:
... # Resource is released at the end of this block,
... # even if code in the block raises an exception
被修饰的函数在调用时必须返回一个生成器-迭代器。这个迭代器必须恰好生成一个值,如果有的话,这个值将绑定到with语句的as子句中的目标。
当生成器yield时,将执行嵌套在with语句中的块。然后在块退出后恢复生成器。如果一个未处理的异常出现在块中,它在生成器中yield那个点产生。因此,你能够使用try…except…finally 语句去陷入错误(如果有的话),或者保证一些清理发生。如果一个异常仅仅为了记录记录或者去执行一定的动作(而不是完全压制它),产生必须抛出那个异常。否则产生器上下文管理器会指定with语句到exeption可以操作的地方,执行将在with语句之后立即恢复。
contextlib.nested(mgr1[, mgr2[, …]]):结合多个上下文管理者到一个单一嵌套的上下文管理者。[被弃用了]
这个函数已经被弃用,而是支持with语句的多重管理器形式。
这个函数相对于with语句的多个管理器形式的一个优点是,参数解包允许它与数量可变的上下文管理器一起使用,如下所示:
from contextlib import nested
with nested(*managers):
do_something()
注意,如果某个嵌套上下文管理器的_exit__()方法指出应该抑制异常,则不会将任何异常信息传递给任何剩余的外部上下文管理器。类似地,如果其中一个嵌套管理器的_exit__()方法引发异常,则将丢失之前的任何异常状态;新的异常将传递给任何剩余外部上下文管理器的_exit__()方法。一般来说,exit_()方法应该避免引发异常,特别是它们不应该重新引发传入的异常。
这个函数有两个主要的怪癖导致它被弃用。首先,由于上下文管理器都是在调用函数之前构造的,所以内部上下文管理器的_new__()和_init__()方法实际上并不在外部上下文管理器的范围内。这意味着,例如,使用嵌套()打开两个文件是一个编程错误,因为如果打开第二个文件时抛出异常,那么第一个文件不会立即关闭。
其次,如果其中一个内部上下文管理器的方法引发一个异常,该异常被外部上下文管理器的方法捕获并抑制,那么这个构造将引发RuntimeError,而不是跳过with语句的主体。
需要支持可变数量上下文管理器嵌套的开发人员可以使用warnings模块来禁止该函数发出的DeprecationWarning,也可以使用该函数作为应用程序特定实现的模型。
在 Python 2.5, 文件有了 enter 和__exit__ 两个方法;前者打开文件本身,后者关闭对象
>>> f = open(“x.txt”)
>>> f
<open file ‘x.txt’, mode ‘r’ at 0x00AE82F0>
>>> f.enter()
<open file ‘x.txt’, mode ‘r’ at 0x00AE82F0>
>>> f.read(1)
‘X’
>>> f.exit(None, None, None)
>>> f.read(1)
Traceback (most recent call last):
File “”, line 1, in
ValueError: I/O operation on closed file
所以,去打开一个文件,处理它的内容,然后保证关闭它,你们简单地这么做:
with open(“x.txt”) as f:
data = f.read()
do something with data
**contextlib.closing(thing)**返回一个上下文管理器,该上下文管理器在块完成时关闭对象。这基本上相当于:
from contextlib import contextmanager
@contextmanager
def closing(thing):
try:
yield thing
finally:
thing.close()
你也可以这么写:
from contextlib import closing
import urllib
with closing(urllib.urlopen('http://www.python.org')) as page:
for line in page:
print line
不需要显式关闭页面。即使出现错误,在退出with块时也将调用page.close()。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。