【问题标题】:Python3. How to correctly raise exception inside context manager to handle it out of with operator?蟒蛇3。如何在上下文管理器中正确引发异常以使用操作员处理它?
【发布时间】:2019-10-28 11:15:59
【问题描述】:

我想捕获在上下文管理器中引发的异常。我创建了一个简单的例子来重现这个问题。

所以,我的上下文管理器:

class Test(object):
    def div(self, a, b):
        return a // b
    def __enter__(self):
        print('enter')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit')
        return self 

以及我想使用它的类:

class Container(object):
    def test_exc(self, a, b):
        try:
            with Test() as test:
                try:
                    result = test.div(a, b)
                    print(a, '/', b, '=', result)
                    return result
                except Exception as e:
                    raise e
        except Exception as e:
            print(e)

用法:

c = Container()
c.test_exc(5, 1)
c.test_exc(5, 0)

输出:

enter
5 / 1 = 5
exit
enter
exit

因此,当引发异常时(在上面的示例中为 ZeroDivisionError),它不会被父级 try...catch 捕获。如何解决这个问题?

【问题讨论】:

    标签: python python-3.x exception contextmanager


    【解决方案1】:

    错误是您的__exit__() 函数的实现。

    文档说明:

    从此方法返回真值将导致 with 语句 抑制异常并继续执行该语句 紧跟 with 语句。否则异常 此方法完成执行后继续传播。 执行此方法期间发生的异常将替换任何 在 with 语句的主体中发生的异常。

    只需删除

    return self
    

    来自__exit__() 函数。 没有返回将返回None,其计算结果为False

    【讨论】:

      【解决方案2】:

      我认为上下文管理器可以选择性地传递它们捕获的异常。

      要停止异常,__exit__ 方法应返回 True(并且 self 可能算作 True

      要传递异常,请返回False

          def __exit__(self, exc_type, exc_val, exc_tb):
              print('exit')
              return False
      

      请参阅此link 到 PEP,其中一些伪代码显示了异常是如何被吞没的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-30
        • 2014-09-01
        • 1970-01-01
        • 2020-06-07
        • 2015-03-25
        • 2015-05-29
        • 2019-11-30
        • 1970-01-01
        相关资源
        最近更新 更多