【问题标题】:Why does my contextmanager-function not work like my contextmanager class in python?为什么我的 contextmanager-function 不像我在 python 中的 contextmanager 类那样工作?
【发布时间】:2013-03-16 08:19:15
【问题描述】:

在我的代码中,我需要能够正确打开和关闭设备,因此需要使用上下文管理器。虽然上下文管理器通常被定义为具有__enter____exit__ 方法的类,但似乎也可以装饰一个函数以与上下文管理器一起使用(参见a recent postanother nice example here)。

在以下(工作)代码 sn-p 中,我实现了两种可能性;只需要将注释行与另一行交换即可:

import time
import contextlib

def device():
    return 42

@contextlib.contextmanager
def wrap():
    print("open")
    yield device
    print("close")
    return

class Wrap(object):
    def __enter__(self):
        print("open")
        return device
    def __exit__(self, type, value, traceback):
        print("close")


#with wrap() as mydevice:
with Wrap() as mydevice:
    while True:
        time.sleep(1)
        print mydevice()

我尝试运行代码并使用CTRL-C 停止它。当我在上下文管理器中使用Wrap 类时,__exit__ 方法被调用为预期的(文本'close' 打印在终端中),但是当我用wrap 函数尝试同样的事情时,文本“关闭”不会打印到终端。

我的问题:代码 sn-p 是否有问题,我是否遗漏了什么,或者为什么没有使用装饰函数调用行 print("close")

【问题讨论】:

    标签: python python-2.7 contextmanager


    【解决方案1】:

    contextmanager 文档中的示例有些误导。 yield 之后的函数部分并不真正对应于上下文管理器协议的__exit__。文档中的关键点是这样的:

    如果块中发生未处理的异常,它会在生成器中在发生 yield 的地方重新引发。因此,您可以使用try...except...finally 语句来捕获错误(如果有),或确保进行一些清理。

    因此,如果您想在 contextmanager 装饰的函数中处理异常,则需要编写自己的 try 来包装 yield 并自己处理异常,在 finally 中执行清理代码(或者只是阻止except 中的异常并在try/except 之后执行清理)。例如:

    @contextlib.contextmanager
    def cm():
        print "before"
        exc = None
        try:
            yield
        except Exception, exc:
            print "Exception was caught"
        print "after"
        if exc is not None:
            raise exc
    
    >>> with cm():
    ...     print "Hi!"
    before
    Hi!
    after
    
    >>> with cm():
    ...     print "Hi!"
    ...     1/0
    before
    Hi!
    Exception was caught
    after
    

    This page 还展示了一个具有启发性的示例。

    【讨论】:

      猜你喜欢
      • 2022-11-23
      • 1970-01-01
      • 2014-08-21
      • 2022-11-12
      • 1970-01-01
      • 2016-10-23
      • 2012-02-16
      • 2011-09-29
      • 2010-10-13
      相关资源
      最近更新 更多