捕获 numpy runtimewarning 作为异常并抑制它们

spa*_*Ash 3 python json warnings numpy exception

我知道这里已经部分回答了这个问题

无论如何,我不确定我是否实现了我想要的。我将简要说明我在做什么:

  • 阅读大量具有特别嵌套结构的 json 文件列表。
  • 从它们中提取最低级别的值并在这些值是列表时取平均值。
  • 将这些值收集到 numpy 数组中。
  • 将我的 numpy 数组转储到腌制文件中。

一切都很顺利,但我收到了一些 numpy 运行时警告:

  • RuntimeWarning: Mean of empty slice.
  • RuntimeWarning: invalid value encountered in double_scalars

给我带来麻烦的函数是实际提取执行此操作的值的函数: v = np.mean(v)

我知道错误可能是由零列表或一些 NaN/Inf 或值中的任何内容引起的。

我想通过从我的数据集中扔掉当前的 .json 样本来摆脱它们。

所以我设置了: np.seterr(all='warn')

我编写了这个笨拙的代码来试图抓住它:

def ExtracValues(d):
    for v in d.values():
        if isinstance(v, dict):
            yield from ExtracValues(v)
        else:
            if isinstance(v,list):
                # v = np.mean(v)            #just averaging vectorial values of features.   #it may be here that raises the empty slice warning of numpy.
                try:
                    v = np.mean(v)
                except Warning:
                    return #trying to trash samples which are no behaving good                  
            yield v
Run Code Online (Sandbox Code Playgroud)

我的问题是我不知道它是否有效工作,因为警告仍然打印在标准输出上。我想代码应该在设置后停止all="Warning",但我如何轻松检查我是否正确?

另外,是否有更pythonic的方法来缩短该函数。我真的不喜欢那样try/except嵌套。

spa*_*Ash 5

感谢 Jürg Merlin Spaak 的评论,我找到了一个更好更简单的解决方案。在我恢复到原始版本的函数之外捕获异常显然更好:

def ExtractValues(d):
    for v in d.values():
        if isinstance(v, dict):
            yield from ExtractValues(v)
        else:
            if isinstance(v,list):
                v = np.mean(v)  
            yield v
Run Code Online (Sandbox Code Playgroud)

我已经在代码的主要部分设置了警告:

np.seterr(all='warn')
Run Code Online (Sandbox Code Playgroud)

然后抓住他们:

with warnings.catch_warnings():
                    warnings.filterwarnings('error')
                    try:
                        raw_features = list(ExtractValues(data)) 
                    except Warning as e:
                        print('Houston, we have a warning:', e)
                        print('The bad guy is: ' + current_file)
                        print('This sample will not be considered.')
                        pass
                    else:
                        #Whatever
Run Code Online (Sandbox Code Playgroud)

值得注意的是,无论谁来这里都是为了同样的例外。我成功地捕捉到了两个警告,但print(e)只会告诉你“空切片的平均值”。我能猜到原因,但我太累了,无法进一步调查。