简体   繁体   English

如何完全重置警告

[英]How to reset warnings completely

How can I see a warning again without restarting python. 如何在不重新启动python的情况下再次看到警告。 Now I see them only once. 现在我只看到一次。

Consider this code for example: 请考虑以下代码,例如:

import pandas as pd  
pd.Series([1]) / 0

I get 我懂了

RuntimeWarning: divide by zero encountered in true_divide 

But when I run it again it executes silently. 但是,当我再次运行它时,它会静默执行。

How can I see the warning again without restarting python? 如何在不重新启动python的情况下再次看到警告?


I have tried to do 我试图做

del __warningregistry__

but that doesn't help. 但这无济于事。

Seems like only some types of warnings are stored there. 似乎只有某些类型的警告存储在此处。 For example if I do: 例如,如果我这样做:

def f():   
    X = pd.DataFrame(dict(a=[1,2,3],b=[4,5,6]))
    Y = X.iloc[:2]
    Y['c'] = 8

then this will raise warning only first time when f() is called. 那么这只会在第一次调用f()时发出警告。 However, now when if do del __warningregistry__ I can see the warning again. 但是,现在如果进行del __warningregistry__我可以再次看到警告。


What is the difference between first and second warning? 第一次警告和第二次警告有什么区别? Why only the second one is stored in this __warningregistry__ ? 为什么只有第二个存储在此__warningregistry__ Where is the first one stored? 第一个存储在哪里?

How can I see the warning again without restarting python? 如何在不重新启动python的情况下再次看到警告?

As long as you do the following at the beginning of your script, you will not need to restart. 只要您在脚本的开头执行以下操作,就无需重新启动。

import pandas as pd
import numpy as np
import warnings
np.seterr(all='warn')
warnings.simplefilter("always")

At this point every time you attempt to divide by zero, it will display 此时,每次您尝试除以零时,它将显示

RuntimeWarning: divide by zero encountered in true_divide 

Explanation: 说明:

We are setting up a couple warning filters. 我们正在设置几个警告过滤器。 The first ( np.seterr ) is telling NumPy how it should handle warnings. 第一个( np.seterr )告诉NumPy应该如何处理警告。 I have set it to show warnings on all , but if you are only interested in seeing the Divide by zero warnings, change the parameter from all to divide . 我已将其设置为对所有警告显示,但是如果您只想查看被零除警告,请将参数从all更改为divide

Next we change how we want the warnings module to always display warnings. 接下来,我们更改希望warnings模块始终显示警告的方式。 We do this by setting up a warning filter . 为此,我们设置了警告过滤器

What is the difference between first and second warning? 第一次警告和第二次警告有什么区别? Why only the second one is stored in this __warningregistry__? 为什么只有第二个存储在此__warningregistry__中? Where is the first one stored? 第一个存储在哪里?

This is described in the bug report reporting this issue: 在报告此问题的错误报告中对此进行了描述:

If you didn't raise the warning before using the simple filter, this would have worked. 如果您在使用简单过滤器之前未发出警告,那将奏效。 The undesired behavior is because of __warningsregistry__. 不良行为是由于__warningsregistry__。 It is set the first time the warning is emitted. 第一次发出警告时设置。 When the second warning comes through, the filter isn't even looked at. 当第二个警告通过时,甚至不会查看过滤器。 I think the best way to fix this is to invalidate __warningsregistry__ when a filter is used. 我认为解决此问题的最佳方法是在使用过滤器时使__warningsregistry__无效。 It would probably be best to store warnings data in a global then instead of on the module, so it is easy to invalidate. 最好将警告数据存储在全局变量中,而不是存储在模块中,这样很容易使它失效。

Incidentally, the bug has been closed as fixed for versions 3.4 and 3.5. 顺便说一句,该错误已按照版本3.4和3.5的修复方式关闭。

warnings is a pretty awesome standard library module. warnings是一个很棒的标准库模块。 You're going to enjoy getting to know it :) 您将乐于了解它:)

A little background 一点背景

The default behavior of warnings is to only show a particular warning, coming from a particular line, on its first occurrence. warnings的默认行为是仅在第一次出现时显示来自特定行的特定警告。 For instance, the following code will result in two warnings shown to the user: 例如,以下代码将向用户显示两个警告:

import numpy as np

# 10 warnings, but only the first copy will be shown
for i in range(10):
    np.true_divide(1, 0)

# This is on a separate line from the other "copies", so its warning will show
np.true_divide(1, 0)

You have a few options to change this behavior. 您可以通过几种方法来更改此行为。

Option 1: Reset the warnings registry 选项1:重置警告注册表

when you want python to "forget" what warnings you've seen before, you can use resetwarnings : 当您希望python“忘记”您之前看到的警告时,可以使用resetwarnings

# warns every time, because the warnings registry has been reset
for i in range(10):
    warnings.resetwarnings()
    np.true_divide(1, 0)

Note that this also resets any warning configuration changes you've made. 请注意,这还会重置您所做的所有警告配置更改。 Which brings me to... 带我去...

Option 2: Change the warnings configuration 选项2:更改警告配置

The warnings module documentation covers this in greater detail, but one straightforward option is just to use a simplefilter to change that default behavior. 警告模块文档对此进行了更详细的介绍,但是一个简单的选择就是使用简单的simplefilter器更改默认行为。

import warnings
import numpy as np

# Show all warnings
warnings.simplefilter('always')
for i in range(10):
    # Now this will warn every loop
    np.true_divide(1, 0)

Since this is a global configuration change, it has global effects which you'll likely want to avoid (all warnings anywhere in your application will show every time). 由于这是全局配置更改,因此可能会产生全局影响,您可能需要避免这种影响(应用程序中任何位置的所有警告都会每次显示)。 A less drastic option is to use the context manager: 不太麻烦的选择是使用上下文管理器:

with warnings.catch_warnings():
    warnings.simplefilter('always')
    for i in range(10):
        # This will warn every loop
        np.true_divide(1, 0)

# Back to normal behavior: only warn once
for i in range(10):
    np.true_divide(1, 0)

There are also more granular options for changing the configuration on specific types of warnings. 对于更改特定类型的警告,还有更详细的选项可用于更改配置。 For that, check out the docs . 为此,请查看docs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM