问题 从python __exit__块中重新分配异常


从一个内部 __exit__ 自定义游标类中的块我想捕获异常,因此我可以抛出更具体的异常。这样做的正确方法是什么?

class Cursor:
    def __enter__(self):
        ...

    def __exit__(self, ex_type, ex_val, tb):
        if ex_type == VagueThirdPartyError:
            # get new more specific error based on error code in ex_val and
            # return that one in its place.
            return False # ?
        else:
            return False

提升内部的具体例外 __exit__ 块似乎是一个黑客,但也许我在想它。


5846
2018-03-11 16:46


起源

为什么只是提出异常似乎是一个黑客? - NPE
我认为可能有另一种方法可以做到这一点,因为上下文管理器捕获主块中的任何异常,存储它,然后将其传递给 出口 批准或否决。内部提升 出口 似乎更多的是基于其论点扩大其责任 - 但我显然在考虑它。 - jpredham


答案:


正确的程序是在内部引发新的异常 __exit__ 处理程序。

你应该  提出传递的异常;允许上下文管理器链接,在这种情况下,您应该只从处理程序返回一个falsey值。然而,提高自己的例外是完全正常的。

请注意,最好使用身份测试 is 验证传入的异常的类型:

def __exit__(self, ex_type, ex_val, tb):
    if ex_type is VagueThirdPartyError:
        if ex_val.args[0] == 'foobar':
            raise SpecificException('Foobarred!')

        # Not raising a new exception, but surpressing the current one:
        if ex_val.args[0] == 'eggs-and-ham':
            # ignore this exception
            return True

        if ex_val.args[0] == 'baz':
            # re-raise this exception
            return False

    # No else required, the function exits and `None` is  returned

你也可以使用 issubclass(ex_type, VagueThirdPartyError) 允许特定异常的子类。


16
2018-03-11 16:50



或者可能: if issubclass(ex_type,VagueThirdPartyError) - mgilson
TL;博士 对于Google员工:自定义 __exit__ 不传播异常?不返回任何东西/返回虚假值。 - Qix