当前位置:   article > 正文

python-contextlib_python contextlib

python contextlib

python-contextlib


用于with-statement上下文的实用程序。
此模块为涉及with语句的常见任务提供实用程序。有关更多信息,请参见上下文管理器类型和语句上下文管理器。

提供函数:
**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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

被修饰的函数在调用时必须返回一个生成器-迭代器。这个迭代器必须恰好生成一个值,如果有的话,这个值将绑定到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()
  • 1
  • 2
  • 3

注意,如果某个嵌套上下文管理器的_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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

你也可以这么写:

from contextlib import closing
import urllib

with closing(urllib.urlopen('http://www.python.org')) as page:
    for line in page:
        print line
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

不需要显式关闭页面。即使出现错误,在退出with块时也将调用page.close()。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/130318
推荐阅读
相关标签
  

闽ICP备14008679号