Joh*_* K. 151 python warnings numpy exception divide-by-zero
我必须在Python中为我正在做的项目制作拉格朗日多项式.我正在做一个重心的样式,以避免使用显式的for循环而不是Newton的分割差异样式.我遇到的问题是我需要将除法除以零,但Python(或者可能是numpy)只是使它成为警告而不是正常的异常.
所以,我需要知道的是抓住这个警告,好像它是一个例外.我在本网站上发现的相关问题没有按照我需要的方式回答.这是我的代码:
import numpy as np
import matplotlib.pyplot as plt
import warnings
class Lagrange:
def __init__(self, xPts, yPts):
self.xPts = np.array(xPts)
self.yPts = np.array(yPts)
self.degree = len(xPts)-1
self.weights = np.array([np.product([x_j - x_i for x_j in xPts if x_j != x_i]) for x_i in xPts])
def __call__(self, x):
warnings.filterwarnings("error")
try:
bigNumerator = np.product(x - self.xPts)
numerators = np.array([bigNumerator/(x - x_j) for x_j in self.xPts])
return sum(numerators/self.weights*self.yPts)
except Exception, e: # Catch division by 0. Only possible in 'numerators' array
return yPts[np.where(xPts == x)[0][0]]
L = Lagrange([-1,0,1],[1,0,1]) # Creates quadratic poly L(x) = x^2
L(1) # This should catch an error, then return 1.
Run Code Online (Sandbox Code Playgroud)
执行此代码时,我得到的输出是:
Warning: divide by zero encountered in int_scalars
Run Code Online (Sandbox Code Playgroud)
这是我想要捕捉的警告.它应该出现在列表理解中.
Bak*_*riu 177
您的配置似乎正在使用以下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])
Run Code Online (Sandbox Code Playgroud)
这意味着您看到的警告不是真正的警告,但只是打印了一些字符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!
Run Code Online (Sandbox Code Playgroud)
请仔细阅读文档,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:
Run Code Online (Sandbox Code Playgroud)
ali*_*i_m 35
添加一点@Bakuriu的回答:
如果您已经知道可能发生警告的位置,那么使用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
Run Code Online (Sandbox Code Playgroud)
ntk*_*tk4 26
为了详细说明@ Bakuriu上面的答案,我发现这使我能够以类似的方式捕获运行时警告,以便我如何捕获错误警告,很好地打印出警告:
import warnings
with warnings.catch_warnings():
warnings.filterwarnings('error')
try:
answer = 1 / 0
except Warning as e:
print('error found:', e)
Run Code Online (Sandbox Code Playgroud)
您可能可以使用warnings.catch_warnings()放置,这取决于您希望通过这种方式捕获错误来构建多大的伞.
Shi*_*hah 14
删除 warnings.filterwarnings 并添加:
numpy.seterr(all='raise')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
96470 次 |
| 最近记录: |