Python上下文管理器没有清理

lem*_*ant 2 python exception-handling contextmanager python-2.7 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()
Run Code Online (Sandbox Code Playgroud)

将输出:

bye from except
Traceback (most recent call last):
  File "", line 15, in 
BaseException
Run Code Online (Sandbox Code Playgroud)

请注意,try/except正确捕获异常,而with语句则没有.有什么我不明白如何使用语句?

你可以在这里看到代码:http://pythonfiddle.com/context-manager-failing


仅供我在OSX小牛队运行python 2.7.虽然我已经能够在许多环境中重现,但我怀疑这与它有很大关系.

Sim*_*ser 10

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

@contextmanager
def say_goodbye():
    try:
        yield
    finally:
        print "bye from context manager"
Run Code Online (Sandbox Code Playgroud)

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

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

正如文件所说:

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

另请注意,这BaseException不是Exception:

>>> isinstance(BaseException(), Exception)
False
Run Code Online (Sandbox Code Playgroud)

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