Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在新函数中组合Python上下文管理器?_Python_Python 2.7 - Fatal编程技术网

如何在新函数中组合Python上下文管理器?

如何在新函数中组合Python上下文管理器?,python,python-2.7,Python,Python 2.7,假设我有两个: 在Python 2.7中,我可以在如下代码块中使用这两种代码: def do_something(): with foo(), bar(): [...] 但是,如何将这两种方法组合成一个单一上下文管理器(为了简洁明了): 我不认为我可以简单地打电话给另外两个上下文管理器,期望它能起作用: @contextmanager def foobar(): # Wrong(?) foo() bar() 由于要成为上下文管理器,基本上需要在

假设我有两个:

在Python 2.7中,我可以在如下代码块中使用这两种代码:

def do_something():
    with foo(), bar():
        [...]
但是,如何将这两种方法组合成一个单一上下文管理器(为了简洁明了):

我不认为我可以简单地打电话给另外两个上下文管理器,期望它能起作用:

@contextmanager
def foobar():
    # Wrong(?)
    foo()
    bar()

由于要成为上下文管理器,基本上需要在某些点上调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
\uuuuuuuuuuuuuuuuuu

如果坚持使用
contextlib.contextmanager
,请再次复制:

被修饰的函数在调用时必须返回生成器迭代器。此迭代器必须只生成一个值,该值将绑定到with语句的as子句中的目标(如果有)

在生成器生成时,将执行with语句中嵌套的块。然后,在模块退出后,发电机恢复运行。如果块中发生未处理的异常,则会在发生屈服点的生成器内部重新调用该异常。因此,您可以使用try…except…finally语句来捕获错误(如果有),或者确保进行一些清理。如果捕获异常只是为了记录它或执行某些操作(而不是完全抑制它),则生成器必须重新释放该异常。否则,生成器上下文管理器将向with语句指示异常已被处理,并将在with语句之后立即使用该语句继续执行


看起来这是可行的,尽管我不确定是否所有角落的案件都得到了处理:

from contextlib import contextmanager

@contextmanager
def bar():
    try:
        print 'enter bar'
        yield
    finally:
        print 'exit bar'

@contextmanager
def foo():
    try:
        print 'enter foo'
        yield
    finally:
        print 'exit foo'

@contextmanager
def foobar():
    try:
        with foo(), bar():
            print 'enter foobar'
            yield
    finally:
        print 'exit foobar'

with foobar():
    print 'hey'

enter foo
enter bar
enter foobar
hey
exit bar
exit foo
exit foobar

您可以将多个上下文管理器组合到一个嵌套的上下文管理器中,但它是从2.7版开始的。
with
语句正在执行嵌套的工作。更多信息。

您可以使用
contextlib.nested
(包装在lambda中,以延迟创建单独的上下文管理器)。但是,Python2.7中不推荐使用此函数,因为在一个
with
语句中可以有多个上下文管理器。使用两个不同的上下文管理器不会重复您自己的操作,除非您经常和/或专门使用这两个上下文管理器

something = lambda : contextlib.nested(foo(), bar())
with something():
    # ...
(有些人可能不喜欢在此处使用
lambda
代替
def
语句:

def something():
    return contextlib.nested(foo(), bar())

)

调用两个不同的上下文管理器不会重复您自己的操作。将它们结合起来似乎是不必要的,除非你经常同时使用它们。
from contextlib import contextmanager

@contextmanager
def bar():
    try:
        print 'enter bar'
        yield
    finally:
        print 'exit bar'

@contextmanager
def foo():
    try:
        print 'enter foo'
        yield
    finally:
        print 'exit foo'

@contextmanager
def foobar():
    try:
        with foo(), bar():
            print 'enter foobar'
            yield
    finally:
        print 'exit foobar'

with foobar():
    print 'hey'

enter foo
enter bar
enter foobar
hey
exit bar
exit foo
exit foobar
something = lambda : contextlib.nested(foo(), bar())
with something():
    # ...
def something():
    return contextlib.nested(foo(), bar())