With 语句的异常未传递给自定义上下文管理器 __exit__
Exception from With statement is not passed to custom context manager __exit__
我正在试验 With 语句和自定义上下文管理器。我不明白为什么执行 With 语句时引发的异常没有传递到我的自定义上下文管理器 __exit__()
?
带有自定义上下文管理器的class如下:
class with_point():
def __init__(self, numer, denom):
self.numer = numer
self.denom = denom
def __enter__(self):
print("This is entry point")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("An error of type {} with value {} happened".format(exc_type,exc_value))
if exc_type is None:
return True
else:
return False
class应该接受两个数值,以后用作分数的分子和分母。
接下来我 运行 使用 With 语句创建 with_point
类型的对象并计算分数的代码:
from with_class import with_point
with with_point(8,0) as wp:
try:
fr = wp.numer / wp.denom
except Exception as e:
print(e)
当我 运行 后一个代码输出如下:
This is entry point
division by zero
An error of type None with value None happened
这与我的预期相反,因为语言参考 indicates
The context manager’s __exit__()
method is invoked. If an exception
caused the suite to be exited, its type, value, and traceback are
passed as arguments to __exit__()
. Otherwise, three None arguments are
supplied.
我希望根据文档将 除以零 异常传递给 __exit__
上下文管理器。然而,这并没有发生,上下文管理器收到 None.
我在这里搜索了一些类似的问题,找到了 and this。首先 link 没有帮助,因为它建议 return False 从 __exit__
如果在 With 语句中引发异常,这正是我所做的。第二个 link 建议在 __exit__
处理程序中引发一个新异常,这可能是个好主意,但它没有说明为什么 'None' 异常从 With 语句而不是`传递到上下文管理器除以零异常。
我需要在 (1) 自定义上下文管理器 (2) With 语句 (3) 中更改什么,以便将 DivideByZero 异常从 With 语句传递给 __exit__
处理程序?
如文档所述:
If an exception caused the suite to be exited, its type, value, and
traceback are passed as arguments to __exit__()
. Otherwise, three None
arguments are supplied.
在你的案例中,“被零除”例外并没有导致诉讼退出,因为你在 except Exception as e:
部分除外!所以它被静音了。如果你删除 try/except,你会看到它传递给了 __exit__
,因为它现在在 with 语句中未被处理,它会导致 suit 退出。
要使 __exit__
中的异常静音,文档说:
If an exception is supplied, and the method wishes to suppress the
exception (i.e., prevent it from being propagated), it should return a
"true" value. Otherwise, the exception will be processed normally upon
exit from this method.
最好的方法是:
class with_point:
def __init__(self, numer, denom):
self.numer = numer
self.denom = denom
def __enter__(self):
print("This is entry point")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("An error of type '{}' with value '{}' happened".format(exc_type, exc_value))
return isinstance(exc_value, ZeroDivisionError)
with with_point(8, 0) as wp:
fr = wp.numer / wp.denom
这就是您通常处理上下文管理器的方式。如果异常是 ZeroDivisionError
它将被沉默,否则它会传播。尝试:
with with_point(8, '0') as wp:
fr = wp.numer / wp.denom
我正在试验 With 语句和自定义上下文管理器。我不明白为什么执行 With 语句时引发的异常没有传递到我的自定义上下文管理器 __exit__()
?
带有自定义上下文管理器的class如下:
class with_point():
def __init__(self, numer, denom):
self.numer = numer
self.denom = denom
def __enter__(self):
print("This is entry point")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("An error of type {} with value {} happened".format(exc_type,exc_value))
if exc_type is None:
return True
else:
return False
class应该接受两个数值,以后用作分数的分子和分母。
接下来我 运行 使用 With 语句创建 with_point
类型的对象并计算分数的代码:
from with_class import with_point
with with_point(8,0) as wp:
try:
fr = wp.numer / wp.denom
except Exception as e:
print(e)
当我 运行 后一个代码输出如下:
This is entry point
division by zero
An error of type None with value None happened
这与我的预期相反,因为语言参考 indicates
The context manager’s
__exit__()
method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to__exit__()
. Otherwise, three None arguments are supplied.
我希望根据文档将 除以零 异常传递给 __exit__
上下文管理器。然而,这并没有发生,上下文管理器收到 None.
我在这里搜索了一些类似的问题,找到了 __exit__
如果在 With 语句中引发异常,这正是我所做的。第二个 link 建议在 __exit__
处理程序中引发一个新异常,这可能是个好主意,但它没有说明为什么 'None' 异常从 With 语句而不是`传递到上下文管理器除以零异常。
我需要在 (1) 自定义上下文管理器 (2) With 语句 (3) 中更改什么,以便将 DivideByZero 异常从 With 语句传递给 __exit__
处理程序?
如文档所述:
If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to
__exit__()
. Otherwise, three None arguments are supplied.
在你的案例中,“被零除”例外并没有导致诉讼退出,因为你在 except Exception as e:
部分除外!所以它被静音了。如果你删除 try/except,你会看到它传递给了 __exit__
,因为它现在在 with 语句中未被处理,它会导致 suit 退出。
要使 __exit__
中的异常静音,文档说:
If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a "true" value. Otherwise, the exception will be processed normally upon exit from this method.
最好的方法是:
class with_point:
def __init__(self, numer, denom):
self.numer = numer
self.denom = denom
def __enter__(self):
print("This is entry point")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("An error of type '{}' with value '{}' happened".format(exc_type, exc_value))
return isinstance(exc_value, ZeroDivisionError)
with with_point(8, 0) as wp:
fr = wp.numer / wp.denom
这就是您通常处理上下文管理器的方式。如果异常是 ZeroDivisionError
它将被沉默,否则它会传播。尝试:
with with_point(8, '0') as wp:
fr = wp.numer / wp.denom