Python上下文管理器没有清理

时间:2014-11-21 22:35:09

标签: python python-2.7 exception-handling contextmanager try-except

当我在上下文管理器中引发任何异常时,不会运行清理代码。例如:

from contextlib import contextmanager

try:
    raise BaseException()
except BaseException:
    print "bye from except"


@contextmanager
def say_goodbye():
    yield
    print "bye from context manager"

with say_goodbye():
    raise BaseException()

将输出:

bye from except
Traceback (most recent call last):
  File "", line 15, in 
BaseException

请注意,try / except正确捕获异常,而with语句则没有。 是否有一些我不了解的陈述如何起作用?

您可以在此处查看代码:http://pythonfiddle.com/context-manager-failing


仅供参考我在OSX mavericks上运行python 2.7。虽然我已经能够在许多环境中重现,但我怀疑这与它有很大关系。

1 个答案:

答案 0 :(得分:10)

您需要自己添加异常处理:

@contextmanager
def say_goodbye():
    try:
        yield
    finally:
        print "bye from context manager"

以上确保finally块始终运行,而不管with块内是否有异常。如果你想要处理异常,你需要抓住它们并可能重新加注:

@contextmanager
def say_goodbye():
    try:
        yield
    except Exception as exc:
        print(exc)
    finally:
        print "bye from context manager"

正如the documentation所说:

  

如果块中发生未处理的异常,则会在生成器发生的位置对其进行重新加载。因此,您可以使用try ... except ... finally语句来捕获错误(如果有),或者确保进行一些清理。

另请注意,BaseException不是Exception

>>> isinstance(BaseException(), Exception)
False

您自己的例外应该继承自Exception,而不是BaseException