【问题标题】:Why do exceptions disappear if I return self in an __exit__ method?如果我在 __exit__ 方法中返回 self,为什么异常会消失?
【发布时间】:2020-05-26 17:32:36
【问题描述】:

我在 Python 3.6 中遇到了一个有趣的现象。如果我在类的__exit__ 方法中返回self,似乎在使用所述类的with 块中引发的任何异常都会消失。我不知道它为什么会发生,而且这似乎不是理想的行为。使用以下代码,我可以重现它:

class SomeObject(object):
    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        return self


if __name__ == '__main__':
    with SomeObject():
        print('This print statement works')
        raise Exception('This exception is not raised for some reason')
    print('This statement is printed as if nothing happened')

这导致我提出以下问题:

  • 你能重现这个还是只有我一个人?
  • 异常是否应该消失(即是否有充分的理由)?如果是,为什么?

【问题讨论】:

    标签: python python-3.x exception


    【解决方案1】:

    __exit__ 决定是否引发异常的方式是基于返回值的“真相”。由于类实例在布尔运算中将评估为 True;不会引发错误。如果返回值为 False,则会引发错误。

    【讨论】:

    • 重新-raised”。我认为一个更好的说法是,如果__exit__ 返回一个真值,那么它被认为已经处理了异常并且它不应该通过调用堆栈向上传递。这就是with pytest.raises(...): 的工作原理。
    【解决方案2】:

    这里是document

    退出与此对象相关的运行时上下文。参数 描述导致上下文退出的异常。如果 context 无一例外地退出,所有三个参数都将是 没有。

    如果提供了异常,并且该方法希望抑制 异常(即,阻止它被传播),它应该返回一个 真正的价值。否则,异常将正常处理 退出此方法。

    请注意,exit() 方法不应重新引发传入的 例外;这是调用者的责任。

    我们可以看到,如果你想抑制异常,你可以返回一个真值。而一个对象被评估为True。所以你的异常被抑制了。

    【讨论】:

    • 我应该在问之前检查一下???
    猜你喜欢
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    • 1970-01-01
    • 2013-04-18
    • 2013-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多