import warnings
def warn():
with warnings.catch_warnings():
warnings.simplefilter('always')
warnings.warn('warning')
with warnings.catch_warnings():
warnings.simplefilter('ignore')
warn()
warn.py:6: UserWarning: warning
warnings.warn('warning')
I was thinking that the 'ignore' filter would apply but it seems the 'always' filter within the function is taking priority. Is this the expected behavior? Is there any way to ignore a warning in this case? I am importing something with simplefilter('always'), so I do not have control, but I would like to ignore it.
Related
I have defined a function in __init__.py.
While running pylint on __init__.py, it gives a warning about unused_variable on the function_name.
I don't want to disable this warning in general (for actual unused variables, etc.) but obviously I don't want a warning for the function definition. Sample __init__.py:
import os
test_enabled = True
run_all_tests = False ## Raises 'unused_variable' warning, expected and want to keep such warnings
def is_test_enabled(): ## Raises 'unused_variable' warning, unexpected and want to disable
return <test_object> if test_enabled else None
For my code in Python, I would like to call many functions with a specific argument. However, for some functions, that argument does not do anything. Still, I would like to add the argument for compatibility reasons. For example, consider the following minimal working example:
def my_function(unused=False):
""" Function with unused argument. """
return True
Obviously, the argument unused is not used, so Pylint throws a warning:
W0613: Unused argument 'redundant' (unused-argument)
My point is that I do not want to remove the argument unused, because the function my_function will be called in a similar way as many other functions for which unused is used.
My question: How can I avoid the warning from Pylint without removing the optional argument?
Option 1: I can think of two options, but these options do not satisfy me. One option is to add some useless code, such that unused is used, e.g.,
def my_function(unused=False):
""" Function with unused argument. """
if unused:
dummy = 10
del dummy
return True
This feels as a waste of resources and it only clutters the code.
Option 2: The second option is to suppress the warning, e.g., like this:
def my_function(unused=False):
""" Function with unused argument. """
# pylint: disable=unused-argument
return True
I also do not really like this option, because usually Pylint warnings are a sign of bad style, so I am more looking to a different way of coding that avoids this warning.
What other options do I have?
I do not believe disabling some pylint warnings is bad style, as long as it is done carefully with clear intent and as specific as possible. For this purpose it is important to activate the useless-suppression check. When it is active pylint will warn you if some messages are locally disabled for no good reason. Add this to your .pylintrc:
[MESSAGES CONTROL]
enable=useless-suppression
For example I would recommend disabling the exact occurrence of the issue like in the following example:
def my_function(
used,
unused=False, # pylint: disable=unused-argument
):
""" Function with unused argument. """
return used
Adding a leading underscore should also keep pylint from triggering:
def my_function(used, _unused=False):
""" Function with unused argument. """
return used
Another commonly used pattern is the following:
def my_function(used, unused_a, unused_b=False):
""" Function with unused argument. """
_ = (unused_a, unused_b,)
return used
It would be possible to work out a solution by playing around with **kwargs. For example:
def _function_a(one, two=2):
return one + two
def _function_b(one, **kwargs):
return one + kwargs['two']
def _function_c(one, **_kwargs):
return one
def _main():
for _function in [_function_a, _function_b, _function_c]:
print(_function.__name__, _function(1, two=4))
According to the docs you can ignore warnings like this:
#pytest.mark.filterwarnings("ignore:api v1")
def test_foo():
which gives:
But there doesn't seem to be any documentation on this mini-language (is it even a minilanguage?)
How is the match done?
I'm asking this because the following test doesn't ignore the DeprecationWarning raised by importing boto3:
#pytest.mark.filterwarnings("ignore:DeprecationWarning")
def test_ignore_warnings():
import boto3
Pytest outputs:
============================================================================================================================== warnings summary ===============================================================================================================================
/home/rob/dev/time-series/.venv/lib/python3.7/site-packages/botocore/awsrequest.py:624
/home/rob/dev/time-series/.venv/lib/python3.7/site-packages/botocore/awsrequest.py:624: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
class HeadersDict(collections.MutableMapping):
-- Docs: https://docs.pytest.org/en/latest/warnings.html
==================================================================================================================== 1 passed, 1 warnings in 0.36 seconds =====================================================================================================================
The filters work the same way as when you use -W argument with python command (see python --help). The format is described in the documentation of the warnings module. In short it's action:message:category:module:line where action is probably mandatory but the other parts can be omitted.
"ignore:api v1" would try to match the message by defining "a string containing a regular expression that the start of the warning message must match". Since you actually want to match category you can skip message. This means that you just seem to be missing one colon after ignore so this is the correct format:
#pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_ignore_warnings():
import boto3
However, you might apparently still get the warning if it happens during an import of a package outside of a test function. In this case you might need to specify the filter globally as a pytest's argument:
pytest -W "ignore::DeprecationWarning" ./tests/
...or add it to pytest.ini:
[pytest]
filterwarnings =
ignore::DeprecationWarning
If such a global exclusion is undesirable, you can try to limit it to a particular module:
ignore::DeprecationWarning:boto3
Testing
For testing purposes, you can use the following code:
import warnings
def something():
warnings.warn("Test", DeprecationWarning)
#pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_ignore_warnings():
something()
How to disable the filtering of the warnings?
I would like to output several times the same warning, but a filter in the library avoids to output more than once the same warning.
import warnings
for i in range(2):
warnings.warn("warning message")
output:
C:\Users\me\my_script.py:4: UserWarning: warning message
warnings.warn("warning message")
The documentation is here:
https://docs.python.org/2/library/warnings.html
Apparently I have to set "always" in the tuple at the entry of the filter, I don't know how to do so, and where to access this tuple.
You can update warning filters with the warnings.simplefilter() and warnings.filterwarnings() functions; from the module intro:
The determination whether to issue a warning message is controlled by the warning filter, which is a sequence of matching rules and actions. Rules can be added to the filter by calling filterwarnings() and reset to its default state by calling resetwarnings().
To make all warnings repeat beyond the first issue, use
warnings.simplefilter('always')
You can expand on this by adding more details to filter on. For example, your warnings.warn() calls do not specify a category, so the default then is to use warnings.UserWarning; you could add that to the filter:
warnings.simplefilter('always', warnings.UserWarning)
etc. You can use keyword arguments too if you only want to specify some of the filter arguments, such as append=True.
With python 2.7.15rc1, to disable all warnings, I used these two lines of code:
import warnings
warnings.simplefilter("ignore")
I hope it is useful
Trying to avoid having RQ display a warning message (to console) about using the meta dictionary for arbitrary property usage. We are using it as is specified, and the warning continues to display.
The warning displayed is as follows:
/usr/local/lib/python2.7/site-packages/rq/job.py:381: SyntaxWarning: Getting custom properties from the job instance directly will be unsupported as of RQ 0.4. Please use the meta dict to store all custom variables. So instead of this:
job.foo
Use this:
job.meta['foo']
SyntaxWarning)
Basically, it is pretty annoying because it interferes with normal debugging activities.
Any ideas on how to disable this?
Use the built-in warnings module's simplefilter method. Requires use of a context manager. Code example copied wholesale from the linked section:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
Further arguments to simplefilter allow you to filter just the warnings you're getting from the specific place in the code you know about-- probably a good idea so other, new warnings that arise later won't be obscured.