Python上下文管理器未清理

Python上下文管理器未清理,python,python-2.7,exception-handling,contextmanager,try-except,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_goodb

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

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语句则没有。 关于with语句应该如何工作,有什么我不明白的吗

您可以在这里看到小提琴中的代码:



仅供参考,我正在OSX mavericks上运行python 2.7。虽然我能够在许多环境中复制,但我怀疑这与此有多大关系。

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

@contextmanager
def say_goodbye():
    try:
        yield
    finally:
        print "bye from context manager"
上述操作确保无论with块中是否存在异常,
finally
块始终运行。如果希望处理异常,则需要捕获这些异常并可能重新释放它们:

@contextmanager
def say_goodbye():
    try:
        yield
    except Exception as exc:
        print(exc)
    finally:
        print "bye from context manager"
正如上面所说:

如果块中发生未处理的异常,则会在发生屈服点的生成器内部重新调用该异常。因此,您可以使用try…except…finally语句来捕获错误(如果有),或者确保进行一些清理

还要注意,
BaseException
不是
异常

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

您自己的异常应该继承自
Exception
,而不是
BaseException

,这在文档中有详细解释。最后一段完整地描述了它的工作原理,告诉你如何使用
try/
,除了`或
try
/
最后
,等等。