4

我正在从事的一个项目有几个上下文管理器。它即将发货,我遇到了一些我开始恐慌的事情。

我的印象是您不应该重新引发作为参数传递给上下文管理器类的 __exit__ 方法的异常。但是,我正在执行一些测试,似乎上下文管理器正在抑制其中抛出的异常。当我将 __exit__ 方法更改为如下所示时:

def __exit__(self, type_, value, trace):
    if trace is not None:
        print('ERROR IN TRACEBACK: ' + str(value))
        # PYTHON 2.7 RAISE SYNTAX:
        raise type_, value, trace

错误似乎正确通过。

我的问题是:如果 type_、value 和 trace 不是 None,那么在 __exit__ 方法中处理异常的正确方法是什么?提出(重新提出?)这样的异常是不是很糟糕?这是我应该做的吗?

我遇到的错误可能是由其他原因引起的。通常我会彻底测试这一切,但目前我的时间似乎非常有限。我希望有人可以解释这个功能的正确实现和

最终:我可以安全地将 raise type_, value, trace 留在我的上下文管理器 __exit__ 方法中吗?

4

1 回答 1

7

__exit__方法的返回值应指示是否应重新引发传递给它的任何异常(根据文档):

contextmanager.__exit__(exc_type, exc_val, exc_tb)

退出运行时上下文并返回一个布尔标志,指示是否应抑制发生的任何异常。如果在执行 with 语句的主体时发生异常,则参数包含异常类型、值和回溯信息。否则,所有三个参数都是无。

因此,只要您的__exit__方法返回某些东西False-y,就应该在您没有明确执行任何操作的情况下重新引发异常。

此外,文档明确声明不要自己重新引发异常:

传入的异常不应该被显式地重新引发 - 相反,这个方法应该返回一个 false 值来指示该方法成功完成并且不想抑制引发的异常。这允许上下文管理代码(例如 contextlib.nested)轻松检测__exit__() 方法是否实际失败。

于 2014-07-10T21:13:43.507 回答