如何在不重新启动python的情况下再次看到警告。现在我只看到他们一次。
以此代码为例:
import pandas as pd
pd.Series([1]) / 0
我明白了
RuntimeWarning: divide by zero encountered in true_divide
但是,当我再次运行它时,它会静默执行。
如何在不重新启动python的情况下再次看到警告?
我试过这样做
del __warningregistry__
但这没有用。
似乎只存储了某些类型的警告。例如,如果我这样做:
def f():
X = pd.DataFrame(dict(a=[1,2,3],b=[4,5,6]))
Y = X.iloc[:2]
Y['c'] = 8
那么只有在第一次调用f()
时才会发出警告。但是,现在如果做del __warningregistry__
,我可以再次看到警告。
第一次和第二次警告有什么区别?为什么只有第二个存储在这个__warningregistry__
?第一个存储在哪里?
如何在不重新启动python的情况下再次看到警告?
只要在脚本开头执行以下操作,就不需要重新启动。
import pandas as pd
import numpy as np
import warnings
np.seterr(all='warn')
warnings.simplefilter("always")
此时,每次尝试除以零时,都会显示
RuntimeWarning: divide by zero encountered in true_divide
说明:
我们正在设置几个警告过滤器。第一个(np.seterr
)告诉NumPy它应该如何处理警告。我已将其设置为显示所有警告,但如果您只想查看除以零警告,请将参数从all
更改为divide
。
接下来我们改变我们希望warnings
模块始终显示警告的方式。我们通过设置warning filter来做到这一点。
第一次和第二次警告有什么区别?为什么只有第二个存储在__warningregistry__中?第一个存储在哪里?
报告此问题的bug report中描述了这一点:
如果在使用简单过滤器之前没有提出警告,那就可以了。不良行为是因为__warningsregistry__。它是第一次发出警告时设置的。当第二个警告到来时,甚至没有看到过滤器。我认为解决此问题的最佳方法是在使用过滤器时使__warningsregistry__无效。将警告数据存储在全局而不是模块中可能是最好的,因此很容易使其无效。
顺便提一下,bug已经关闭了版本3.4和3.5。
warnings
是一个非常棒的标准库模块。你会喜欢去了解它:)
warnings
的默认行为是仅在第一次出现时显示来自特定行的特定警告。例如,以下代码将导致向用户显示两个警告:
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)
您有几个选项可以更改此行为。
当你想让python“忘记”你之前看过的警告时,你可以使用resetwarnings
:
# warns every time, because the warnings registry has been reset
for i in range(10):
warnings.resetwarnings()
np.true_divide(1, 0)
请注意,这也会重置您所做的任何警告配置更改。这让我想到......
warnings module documentation更详细地介绍了这一点,但一个简单的选择就是使用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)
由于这是全局配置更改,因此它具有您可能希望避免的全局效果(应用程序中的任何位置的所有警告都会每次显示)。一个不太激烈的选择是使用上下文管理器:
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)
还有更精细的选项可用于更改特定类型警告的配置。为此,看看docs。