当我在上下文管理器中引发任何异常时,不会运行清理代码。例如:
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。虽然我已经能够在许多环境中重现,但我怀疑这与它有很大关系。
答案 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
。