在尝试忽略在执行上下文管理器期间引发的异常时,我有哪些选择?原样,以下简单的上下文管理器只传播结果,导致它结束执行,除非被捕获:
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
条款来表达它,但这似乎是一种相当繁琐的方式。当然,有更好的选择来解决这个问题。
答案 0 :(得分:1)
除了将其包装在try
语句中之外,还有另外两种方法可以在上下文管理器中抑制给定的异常:
如果应该抑制给定的异常,则使用返回if
的{{1}}条件。这基于documentation,它指定True
值可以抑制异常。
这将适用于True
和Python 2.x
版本。
将contextlib.suppress
与给定的例外名称一起用作参数。
这仅适用于版本Python 3.x
第一个选项是值得注意的选项,因为它可以在大多数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
也可以写在同一行,但这会产生相当冗长的陈述。显而易见的缺点是,每次使用上下文管理器时它都会引入另一个语句。
即使有两个选项, 也应该有一个 - 最好只有一个 - 显而易见的方式 我相信第二个选项很明显方式(至少对于最近的版本而言)。