简体   繁体   English

Python上下文管理器没有清理

[英]Python context manager not cleaning up

When I raise any exceptions inside a context manager the cleanup code is not run. 当我在上下文管理器中引发任何异常时,不会运行清理代码。 For example: 例如:

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()

Will output: 将输出:

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

Notice that the try/except properly catches the exception while the with statement does not. 请注意,try / except正确捕获异常,而with语句则没有。 Is there something I don't understand about how with statements are supposed to work? 有什么我不明白如何使用语句?

You can see the code in a fiddle here: http://pythonfiddle.com/context-manager-failing 你可以在这里看到代码: http//pythonfiddle.com/context-manager-failing


FYI I'm running python 2.7 on OSX mavericks. 仅供我在OSX小牛队运行python 2.7。 Although I've been able to reproduce in many environments so I doubt that has much to do with it. 虽然我已经能够在许多环境中重现,但我怀疑这与它有很大关系。

You'll need to add exception handling yourself: 您需要自己添加异常处理:

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

The above ensures the finally block always runs regardless of an exception inside the with block. 以上确保finally块始终运行,而不管with块内是否有异常。 If you want exceptions to be handled you'll need to catch those and possible reraise them: 如果你想要处理异常,你需要抓住它们并可能重新加注它们:

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

As the documentation says: 正如文件所说:

If an unhandled exception occurs in the block, it is reraised inside the generator at the point where the yield occurred. 如果块中发生未处理的异常,则在生成器发生的点处将其重新加入。 Thus, you can use a try...except...finally statement to trap the error (if any), or ensure that some cleanup takes place. 因此,您可以使用try ... except ... finally语句来捕获错误(如果有),或确保进行一些清理。

Also note that BaseException is not an Exception : 另请注意, BaseException不是Exception

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

Your own exceptions should inherit from Exception , not BaseException . 您自己的异常应该继承自Exception ,而不是BaseException

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM