如何在Context Manager中抑制给定的异常?

时间:2015-12-06 02:01:36

标签: python python-3.x

在尝试忽略在执行上下文管理器期间引发的异常时,我有哪些选择?原样,以下简单的上下文管理器只传播结果,导致它结束执行,除非被捕获:

class contextMan:    
    def __enter__(self):
        print("Entering Context")

    def __exit__(self, exc_type, exc_value, traceback):
        print("Exiting Context")

if __name__ == "__main__":
    with contextMan():
        raise IndexError

我当然可以用try -- except条款来表达它,但这似乎是一种相当繁琐的方式。当然,有更好的选择来解决这个问题。

1 个答案:

答案 0 :(得分:1)

除了将其包装在try语句中之外,还有另外两种方法可以在上下文管理器中抑制给定的异常:

  1. 如果应该抑制给定的异常,则使用返回if的{​​{1}}条件。这基于documentation,它指定True值可以抑制异常。

    这将适用于TruePython 2.x版本。

  2. contextlib.suppress与给定的例外名称一起用作参数。

    这仅适用于版本Python 3.x

  3. 第一个选项是值得注意的选项,因为它可以在大多数Pythons上工作,因此可移植性点。可以通过使用所需的异常初始化上下文管理器来完成它,并在> 3.3上添加__exit__子句,该子句只允许传播给定的异常:

    if

    现在,这将禁止class contextMan: def __init__(self, exception): self.exception = exception def __enter__(self): print("Entering Context") def __exit__(self, exc_type, exc_value, traceback): print("Exiting Context") return isinstance(exc_value, self.exception) if __name__ == "__main__": with contextMan(IndexError): raise IndexError 的任何实例或IndexError的子类的任何实例,从而导致输出:

    IndexError

    这种方法的缺点是你要为每个实例添加一个额外的属性,并且基本上将两个不同的逻辑任务组合在一个对象中,而不是将它们分开。

    第二个选项是健壮显式一般。它是为这些场景专门创建的 。它也是一个上下文管理器,因此通常可以用于任何特定异常应该被抑制的情况。

    它的呼叫签名的形式如下:

    Entering Context
    Exiting Context
    

    其中 contextlib.suppress(*exceptions) 是要被抑制的异常元组。保持原始上下文管理器的原样,我们现在可以创建一个嵌套的上下文管理器,它也可以抑制特定的异常:

    *exceptions

    也可以写在同一行,但这会产生相当冗长的陈述。显而易见的缺点是,每次使用上下文管理器时它都会引入另一个语句。

    即使有两个选项, 也应该有一个 - 最好只有一个 - 显而易见的方式 我相信第二个选项很明显方式(至少对于最近的版本而言)。