Suppress warnings for python-xarray - python

I'm running the following code
positive_values = values.where(values > 0)
In this example values may contain nan elements. I believe that for this reason, I'm getting the following runtime warning:
RuntimeWarning: invalid value encountered in greater_equal if not reflexive
Does xarray have methods of surpressing these warnings?

The warnings module provides the functionality you are looking for.
To suppress all warnings do (see John Coleman's answer for why this is not good practice):
import warnings
warnings.simplefilter("ignore")
# warnings.simplefilter("ignore", category=RuntimeWarning) # for RuntimeWarning only
To make the suppression temporary do it inside the warnings.catch_warnings() context manager:
import warnings
with warnings.catch_warnings():
warnings.simplefilter("ignore")
positive_values = values.where(values > 0)
The context manager saves the original warning settings prior to entering the context and then sets them back when exiting the context.

As a general rule of thumb, warnings should be heeded rather than suppressed. Either you know what causes the warning or you don't. If you know what causes the warning, there is usually a simple workaround. If you don't know what causes the warning, there is likely a bug. In this case, you can use the short-circuiting nature of & as follows:
positive_values = values.where(values.notnull() & values > 0)

Related

Disable NonInteractiveExampleWarning in python hypothesis

I want to use hypothesis awesome features to create some sample data for my application. I use it roughly like this
from hypothesis import strategies as st
ints = st.integers() #simplified example
ints.example()
I get this warning:
NonInteractiveExampleWarning: The .example() method is good for exploring strategies, but should only be used interactively
Is there a simple way to disable this warning? Just to be clear: I want to use the example data generation outside of a testing and in a non-interactive context and I'm aware of what the warning is referring to. I just want to get rid of it.
The warnings module lets you selectively ignore specific warnings; for example:
from hypothesis.errors import NonInteractiveExampleWarning
from hypothesis import strategies as st
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=NonInteractiveExampleWarning)
ints = st.integers()
print( ints.example() )

Supress UserWarning from torchmetrics

When I train a neural network using PyTorch, I get the following warning caused by the torchmetrics library:
/Users/dev/miniconda/envs/pytorch/lib/python3.10/site-packages/torchmetrics/utilities/prints.py:36:
UserWarning: Torchmetrics v0.9 introduced a new argument class
property called full_state_update that has not been set for this
class (SMAPE). The property determines if update by default needs
access to the full metric state. If this is not the case, significant
speedups can be achieved and we recommend setting this to False. We
provide an checking function from torchmetrics.utilities import check_forward_no_full_state that can be used to check if the
full_state_update=True (old and potential slower behaviour, default
for now) or if full_state_update=False can be used safely.
I tried to suppress this warning by using the warnings package in my script:
with warnings.catch_warnings():
warnings.simplefilter("ignore")
However, the warning is still shown which is probably due to a function in prints.py of torchmetrics:
def _warn(*args: Any, **kwargs: Any) -> None:
warnings.warn(*args, **kwargs)
Is it possible to get rid of this warning from my script without changing the library code?
Use -W argument to control how python deals with warnings, consider following simple example, let dowarn.py content be
import warnings
warnings.warn("I am UserWarning", UserWarning)
warnings.warn("I am FutureWarning", FutureWarning)
then
python dowarn.py
gives
dowarn.py:2: UserWarning: I am UserWarning
warnings.warn("I am UserWarning", UserWarning)
dowarn.py:3: FutureWarning: I am FutureWarning
warnings.warn("I am FutureWarning", FutureWarning)
and
python -W ignore dowarn.py
gives empty output and
python -W ignore::UserWarning dowarn.py
gives
dowarn.py:3: FutureWarning: I am FutureWarning
warnings.warn("I am FutureWarning", FutureWarning)
See python man page for discussion of -W values

scipy overwriting warning filters?

It seems as though some scipy modules are messing with my warning filters. Consider the following code. My understanding is that it should only throw one warning because of the "once" filter I supplied to my custom Warning class. However, the warning after the scipy import gets shown as well.
This is with python 3.7 and scipy 1.6.3.
import warnings
class W(DeprecationWarning): pass
warnings.simplefilter("once", W)
warnings.warn('warning!', W)
warnings.warn('warning!', W)
from scipy import interpolate
warnings.warn('warning!', W)
This only seems to happen when I import certain scipy modules. A generic "import scipy" doesn't do this.
I've narrowed it down to the filters set in scipy.special.sf_error.py and scipy.sparse.__init__.py. I don't see how that code would cause the problem, but it does. When I comment those filtersout, my code works as expected.
Am I misunderstanding something? Is there a work-around that that doesn't involved overwriting warnings.filterwarnings/warnings.simplefilters?
This an open Python bug: https://bugs.python.org/issue29672.
Note, in particular, the last part of the comment by Tom Aldcroft:
Even a documentation update would be useful. This could explain not only catch_warnings(), but in general the unexpected feature that if any package anywhere in the stack sets a warning filter, then that globally resets whether a warning has been seen before (via the call to _filters_mutated()).
The code in scipy/special/sf_error.py sets a warning filter, and that causes a global reset of which warnings have been seen before. (If you add another call of warnings.warn('warning!', W) to the end of your sample code, you should see that it does not raise a warning.)

Specifying the message in warnings.simple_filter() filters based on category not message

When we import our_library in Python2, we have coded it to raise a DeprecationWarning once. Here's the representative code.
our_library/init.py
def _py2_deprecation_warning():
py2_warning = ('Python2 support is deprecated and will be removed in '
'a future release. Consider switching to Python3.')
warnings.filterwarnings('once', message=py2_warning)
warnings.warn(message=py2_warning,
category=DeprecationWarning,
stacklevel=3,
)
def _python_deprecation_warnings():
if sys.version_info.major == 2:
_py2_deprecation_warning()
_python_deprecation_warnings()
We deprecated the parameters in a function in our_library. Here's the representative code:
our_library/some_module.py
def some_function(new_param, deprecated_param):
if deprecated_param:
param_deprecation_msg = (
'The parameter "{}" will be removed in a future version of Nilearn.'
'Please use the parameter "{}" instead.'.format(deprecated_param,
new_param,
)
)
warnings.warn(category=DeprecationWarning,
message=param_deprecation_msg,
stacklevel=3)
Then when we import our library, and call that function, like this:
calling_script.py
from our_library.some_module import some_function
some_function(deprecated_param)
We get the Python2 DeprecationWarning but not the Parameter DeprecationWarning.
DeprecationWarning: Python2 support is deprecated and will be removed in a future release. Consider switching to Python3.
_python_deprecation_warnings()
Now know I can solve this by using a with warnings.catch_warnings(): or resetwarnings(). However I thought that specifying the message explicitly in Python2 Warning will prevent the 'once filter being set for other DeprecationWarnings.
However that is not the case? WhHy is that and how do I make my existing code work without using CatchWarnings or reset warnings?
If I change the Parameter warning to FutureWarning, that I can see.
Why is the first simplefilter blocking all deprecation messages based on category instead of messages?
UPDATE:
with warnings.catch_warnings(): doesn't seem to work either.
def _py2_deprecation_warning():
py2_warning = ('Python2 support is deprecated and will be removed in '
'a future release. Consider switching to Python3.')
with warnings.catch_warnings():
warnings.filterwarnings('once', message=py2_warning)
warnings.warn(message=py2_warning,
category=DeprecationWarning,
stacklevel=3,
)
Nevermind, I had forgotten that DeprecationWarnings are not displayed by defualt. They must specifically be set to be displayed, which I have not done here.

How to reset warnings completely

How can I see a warning again without restarting 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?
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.
However, now when if do del __warningregistry__ I can see the warning again.
What is the difference between first and second warning? Why only the second one is stored in this __warningregistry__? Where is the first one stored?
How can I see the warning again without restarting 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. 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.
Next we change how we want the warnings module to always display 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__? 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__. 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. 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.
warnings is a pretty awesome standard library module. 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. 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
when you want python to "forget" what warnings you've seen before, you can use 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
The warnings module documentation covers this in greater detail, but one straightforward option is just to use a simplefilter to change that default behavior.
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.

Categories

Resources