python - 我如何捕捉一个像异常一样的 numpy 警告(不仅仅是为了测试)?

我必须在 Python 中为我正在做的一个项目创建一个拉格朗日多项式。我正在做一种重心风格,以避免使用显式的 for 循环,而不是使用牛顿的分差风格。我遇到的问题是我需要将除以零,但 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. 

执行这段代码时,我得到的输出是:

Warning: divide by zero encountered in int_scalars

这就是我想要捕捉的警告。它应该出现在列表理解中。

最佳答案

您的配置似乎正在使用 numpy.seterrprint 选项:

>>> 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 的文档)。如果你想捕获它,你可以:

  1. 使用 numpy.seterr(all='raise') 将直接引发异常。然而,这会改变所有操作的行为,因此这是一个相当大的行为变化。
  2. 使用 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: 

https://stackoverflow.com/questions/15933741/

相关文章:

linux - GNU screen 没有响应,似乎被阻塞了

python - 如何将一串字节转换为int?

python - 什么是字典 View 对象?

linux - 如何在 Ubuntu 中增加 Neo4j 的最大文件打开限制(ulimit)?

linux - 使用 bash 历史记录获取先前的命令,复制它,然后 'run' 它但命令注释

python - Django 可选 url 参数

python - 为什么 apt-get 功能在 Mac OS X v10.9 (Mavericks

python - 如何检查两个日期之间的差异(以秒为单位)?

linux - 我可以在已编译的二进制文件中更改 'rpath' 吗?

linux - 如何在 linux bash/shell 中对图像进行 base64 编码