3 回答
TA贡献1850条经验 获得超11个赞
看来您的配置正在使用print选项numpy.seterr:
>>> import numpy as np
>>> np.array([1])/0 #'warn' mode
__main__:1: RuntimeWarning: divide by zero encountered in divide
array([0])
>>> np.seterr(all='print')
{'over': 'warn', 'divide': 'warn', 'invalid': 'warn', 'under': 'ignore'}
>>> np.array([1])/0 #'print' mode
Warning: divide by zero encountered in divide
array([0])
这意味着您看到的警告不是真正的警告,而只是印有一些字符stdout(请参阅文档以获取有关信息seterr)。如果您想抓住它,可以:
使用numpy.seterr(all='raise')它将直接引发异常。但是,这会更改所有操作的行为,因此,这是行为上的很大变化。
使用numpy.seterr(all='warn'),可以将打印的警告转换为真实的警告,您将可以使用上述解决方案来本地化此行为更改。
实际warnings收到警告后,您可以使用该模块来控制警告的处理方式:
>>> import warnings
>>>
>>> warnings.filterwarnings('error')
>>>
>>> try:
... warnings.warn(Warning())
... except Warning:
... print 'Warning was raised as an exception!'
...
Warning was raised as an exception!
请仔细阅读文档,filterwarnings因为它可以使您仅过滤所需的警告并具有其他选项。我还要考虑看看catch_warnings哪个是上下文管理器,它会自动重置原始filterwarnings功能:
>>> import warnings
>>> with warnings.catch_warnings():
... warnings.filterwarnings('error')
... try:
... warnings.warn(Warning())
... except Warning: print 'Raised!'
...
Raised!
>>> try:
... warnings.warn(Warning())
... except Warning: print 'Not raised!'
...
__main__:2: Warning:
TA贡献2065条经验 获得超14个赞
如果您已经知道警告可能在何处发生,那么使用numpy.errstate上下文管理器通常会更干净一些,而不是 numpy.seterr将所有相同类型的后续警告都视为相同,而不管它们在代码中的位置如何:
import numpy as np
a = np.r_[1.]
with np.errstate(divide='raise'):
try:
a / 0 # this gets caught and handled as an exception
except FloatingPointError:
print('oh no!')
a / 0 # this prints a RuntimeWarning as usual
编辑:
在我最初的示例中,我有a = np.r_[0],但是显然numpy的行为发生了变化,使得在分子为全零的情况下,以零除的处理方式有所不同。例如,在numpy 1.16.4中:
all_zeros = np.array([0., 0.])
not_all_zeros = np.array([1., 0.])
with np.errstate(divide='raise'):
not_all_zeros / 0. # Raises FloatingPointError
with np.errstate(divide='raise'):
all_zeros / 0. # No exception raised
with np.errstate(invalid='raise'):
all_zeros / 0. # Raises FloatingPointError
相应的警告消息也不同:1. / 0.记录为RuntimeWarning: divide by zero encountered in true_divide,而0. / 0.记录为RuntimeWarning: invalid value encountered in true_divide。我不知道到底为什么这种变化作出的,但我怀疑它有与事实结果做0. / 0.是不能表示为数字(numpy的回报为NaN在这种情况下),而1. / 0.并-1. / 0.分别返回+ Inf文件和-Inf ,符合IEE 754标准。
如果要捕获两种类型的错误,则可以始终通过np.errstate(divide='raise', invalid='raise'),或者all='raise'如果您想对任何类型的浮点错误引发异常。
TA贡献1995条经验 获得超2个赞
我发现这使我能够以类似于捕获错误警告的方式捕获运行时警告,从而很好地打印警告:
import warnings
with warnings.catch_warnings():
warnings.filterwarnings('error')
try:
answer = 1 / 0
except Warning as e:
print('error found:', e)
您可能可以尝试放置warnings.catch_warnings()的位置,具体取决于您要使用这种方式捕获错误的伞的大小。
添加回答
举报