On this page
28.7. contextlib —具有语句状态的 Util
2.5 版的新Function。
源代码: Lib/contextlib.py
该模块为涉及with语句的常见任务提供 Util。有关更多信息,另请参见上下文 Management 器类型和使用语句上下文 Management 器。
Functions provided:
contextlib.
contextmanager
(* func *)
尽管许多对象本机支持在 with 语句中使用,但有时需要 Management 的资源本身不是上下文 Management 器,并且没有实现与contextlib.closing
一起使用的close()
方法
下面是一个抽象的示例,以确保正确的资源 Management:
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
被修饰的函数在调用时必须返回generator -iterator。此迭代器必须精确地产生一个值,该值将绑定到with语句的as子句中的目标(如果有)。
在生成器屈服的 Moment,执行嵌套在with语句中的块。退出该块后,将恢复生成器。如果在块中发生未处理的异常,则会在生成器内部产生yield的位置将其重新引发。因此,您可以使用try…except…finally语句来捕获错误(如果有),或确保进行一些清除。如果仅出于记录日志或执行某些操作(而不是完全抑制它)的目的捕获了异常,则生成器必须重新引发该异常。否则,生成器上下文 Management 器将向with语句指示已处理了该异常,并且将在with语句之后立即使用该语句 continue 执行。
contextlib.
nested
(* mgr1 * [,* mgr2 * [,* ... *]])- 将多个上下文 Management 器组合到一个嵌套的上下文 Management 器中。
不赞成使用此Function,而推荐使用with语句的多 Management 器形式。
与with语句的多 Management 器形式相比,此Function的一个优势是参数解压缩使它可以与可变数量的上下文 Management 器一起使用,如下所示:
from contextlib import nested
with nested(*managers):
do_something()
请注意,如果嵌套上下文 Management 器之一的exit()方法指示应抑制异常,则不会将异常信息传递给任何剩余的外部上下文 Management 器。同样,如果其中一个嵌套 Management 器的exit()方法引发异常,则任何先前的异常状态都将丢失;新的异常将被传递给所有其余外部上下文 Management 器的exit()方法。通常,exit()方法应避免引发异常,尤其是它们不应重新引发传入的异常。
此Function有两个主要的怪癖,导致不推荐使用。首先,由于上下文 Management 器都是在调用函数之前构建的,因此内部上下文 Management 器的new()和init()方法实际上并未包含在外部上下文 Management 器的范围内。例如,这意味着使用nested()打开两个文件是一个编程错误,因为如果在打开第二个文件时引发异常,则第一个文件将不会立即关闭。
其次,如果内部上下文 Management 器之一的enter()方法引发被外部上下文 Management 器之一的exit()方法捕获并抑制的异常,则此构造将引发RuntimeError而不是跳过with语句的主体。
需要支持可变数量的上下文 Management 器嵌套的开发人员可以使用warnings模块来抑制此Function引发的 DeprecationWarning,也可以将该Function用作特定于应用程序实现的模型。
从 2.7 版开始不推荐使用:with 语句现在直接支持此Function(不存在容易出错的易错问题)。
contextlib.
closing
(* thing *)- 返回一个上下文 Management 器,该 Management 器在块完成时关闭* 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
无需显式关闭page
。即使发生错误,退出with块时也会调用page.close()
。