新的Python,但我试图理解这段代码:
with pytest.raises(ValueError):
group_adjust(vals, [grps_1, grps_2], weights)
在阅读this tutorial on with后,我了解pytest.raises()
会返回一个上下文管理器,用于设置和清除调用group_adjust()
之前和之后的内容。我也理解,如果出现问题,group_adjust()
应该提出ValueError
。
当引发ValueError时,pytest如何“反应”? AFAIK,只有设置和清理所以我不确定它如何捕获异常。最终目标是了解将pytest作为上下文管理器的好处。
答案 0 :(得分:1)
__exit__
魔术函数接受exception_type
,exception_value
和traceback
参数:
In [5]: class RaisesContext:
...: def __enter__(self):
...: return self
...: def __exit__(self, exception_type, exception_value, traceback):
...: print('Exception type:', exception_type)
...: print('Exception value:', exception_value)
...: print('Traceback:', traceback)
...: return True
...:
In [6]: with RaisesContext():
...: raise ValueError('Something went wrong')
...:
Exception type: <class 'ValueError'>
Exception value: Something went wrong
Traceback: <traceback object at 0x7fd92f4a2c48>
如果None
块正常结束,它们为with
:
In [7]: with RaisesContext():
...: pass
...:
Exception type: None
Exception value: None
Traceback: None
答案 1 :(得分:1)
我不完全确定pytest,但任何上下文管理器在其退出时传递3个参数,exc_type,Excepton和Traceback,如果没有异常,则所有三个都没有,如果退出返回True然后也会抑制异常,
在此更好地解释:https://docs.python.org/2/reference/datamodel.html#object.exit
所以,如果我想创建一个简单的处理程序来显示回溯而不停止程序,我可以这样做:
import traceback
class VerboseTry:
def __enter__(self):
pass
def __exit__(self,exc_type,error,trace):
if exc_type:
traceback.print_exception(exc_type,error,trace)
return True
def f(depth=4):
"""this will (needlessly) raise an error with several iterations to the traceback"""
if depth==0:
int("this is going to fail")
else:
return f(depth-1)
print("starting")
with VerboseTry():
f()
print("got to end")
查看在不停止程序的情况下引发的错误。
答案 2 :(得分:1)
with
构造调用两个&#34;魔法&#34;方法,__enter__
和__exit__
分别位于代码块的开头和结尾。因此,
with foo:
x = 1
可以理解为:
foo.__enter__()
x = 1
foo.__exit__()
除非在hir回答中提及,__exit__
会调用为什么代码块正在退出的详细信息:如果是异常,那么是什么类型,None
因此,pytest.raises(TYPE)
返回的对象已配置为期望 TYPE的例外。 __exit__
方法将它接收的参数与声明实际(如果有)异常的参数与存储预期异常类型的内部数据成员进行比较,然后决定是否通过测试。