Check if any tests raise a deprecation warning with pytest - python

I am using pytest to run tests in a Python package, and I would like to know if any of the code that is executed as part of the tests is raising deprecation warnings (when all tests are passing). Does anyone know of a way to do this?

The code
import warnings
warnings.simplefilter("error")
will turn (all) warnings into errors, which may help.
Alternatively, you can get a list of generated warnings with
import warnings
with warnings.catch_warnings(record=True) as w:
warnings.warn("deprecated", DeprecationWarning)
print(w)
#>>> [<warnings.WarningMessage object at 0x7fee80484f50>]
and then assert on that list.

Starting with pytest 3.1, warnings are automatically displayed at the end of the session: see https://docs.pytest.org/en/latest/warnings.html

Related

Function returning either 0 or -inf without warning [duplicate]

I am working with code that throws a lot of (for me at the moment) useless warnings using the warnings library. Reading (/scanning) the documentation I only found a way to disable warnings for single functions. But I don't want to change so much of the code.
Is there a flag like python -no-warning foo.py?
What would you recommend?
Look at the Temporarily Suppressing Warnings section of the Python docs:
If you are using code that you know will raise a warning, such as a deprecated function, but do not want to see the warning, then it is possible to suppress the warning using the catch_warnings context manager:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
I don't condone it, but you could just suppress all warnings with this:
import warnings
warnings.filterwarnings("ignore")
Ex:
>>> import warnings
>>> def f():
... print('before')
... warnings.warn('you are warned!')
... print('after')
...
>>> f()
before
<stdin>:3: UserWarning: you are warned!
after
>>> warnings.filterwarnings("ignore")
>>> f()
before
after
There's the -W option.
python -W ignore foo.py
You can also define an environment variable (new feature in 2010 - i.e. python 2.7)
export PYTHONWARNINGS="ignore"
Test like this: Default
$ export PYTHONWARNINGS="default"
$ python
>>> import warnings
>>> warnings.warn('my warning')
__main__:1: UserWarning: my warning
>>>
Ignore warnings
$ export PYTHONWARNINGS="ignore"
$ python
>>> import warnings
>>> warnings.warn('my warning')
>>>
For deprecation warnings have a look at how-to-ignore-deprecation-warnings-in-python
Copied here...
From documentation of the warnings module:
#!/usr/bin/env python -W ignore::DeprecationWarning
If you're on Windows: pass -W ignore::DeprecationWarning as an argument to Python. Better though to resolve the issue, by casting to int.
(Note that in Python 3.2, deprecation warnings are ignored by default.)
Or:
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning)
import md5, sha
yourcode()
Now you still get all the other DeprecationWarnings, but not the ones caused by:
import md5, sha
Not to make it complicated, just use these two lines
import warnings
warnings.filterwarnings('ignore')
If you don't want something complicated, then:
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
This is an old question but there is some newer guidance in PEP 565 that to turn off all warnings if you're writing a python application you should use:
import sys
import warnings
if not sys.warnoptions:
warnings.simplefilter("ignore")
The reason this is recommended is that it turns off all warnings by default but crucially allows them to be switched back on via python -W on the command line or PYTHONWARNINGS.
When all else fails use this: https://github.com/polvoazul/shutup
pip install shutup
then add to the top of your code:
import shutup; shutup.please()
Disclaimer: I am the owner of that repository. I wrote it after the 5th time I needed this and couldn't find anything simple that just worked.
If you know what are the useless warnings you usually encounter, you can filter them by message.
import warnings
#ignore by message
warnings.filterwarnings("ignore", message="divide by zero encountered in divide")
##part of the message is also okay
warnings.filterwarnings("ignore", message="divide by zero encountered")
warnings.filterwarnings("ignore", message="invalid value encountered")
import sys
if not sys.warnoptions:
import warnings
warnings.simplefilter("ignore")
Change ignore to default when working on the file or adding new functionality to re-enable warnings.
I realise this is only applicable to a niche of the situations, but within a numpy context I really like using np.errstate:
np.sqrt(-1)
__main__:1: RuntimeWarning: invalid value encountered in sqrt
nan
However, using np.errstate:
with np.errstate(invalid='ignore'):
np.sqrt(-1)
nan
The best part being you can apply this to very specific lines of code only.
More pythonic way to ignore WARNINGS
Since 'warning.filterwarnings()' is not suppressing all the warnings, i will suggest you to use the following method:
import logging
for name in logging.Logger.manager.loggerDict.keys():
logging.getLogger(name).setLevel(logging.CRITICAL)
#rest of the code starts here...
OR,
If you want to suppress only a specific set of warnings, then you can filter like this:
import logging
for name in logging.Logger.manager.loggerDict.keys():
if ('boto' in name) or ('urllib3' in name) or ('s3transfer' in name) or ('boto3' in name) or ('botocore' in name) or ('nose' in name):
logging.getLogger(name).setLevel(logging.CRITICAL)
#rest of the code starts here...
warnings are output via stderr and the simple solution is to append '2> /dev/null' to the CLI. this makes a lot of sense to many users such as those with centos 6 that are stuck with python 2.6 dependencies (like yum) and various modules are being pushed to the edge of extinction in their coverage.
this is especially true for cryptography involving SNI et cetera. one can update 2.6 for HTTPS handling using the proc at:
https://urllib3.readthedocs.io/en/latest/user-guide.html#ssl-py2
the warning is still in place, but everything you want is back-ported. the re-direct of stderr will leave you with clean terminal/shell output although the stdout content itself does not change.
responding to FriendFX. sentence one (1) responds directly to the problem with an universal solution. sentence two (2) takes into account the cited anchor re 'disable warnings' which is python 2.6 specific and notes that RHEL/centos 6 users cannot directly do without 2.6. although no specific warnings were cited, para two (2) answers the 2.6 question I most frequently get re the short-comings in the cryptography module and how one can "modernize" (i.e., upgrade, backport, fix) python's HTTPS/TLS performance. para three (3) merely explains the outcome of using the re-direct and upgrading the module/dependencies.

How can I make this Python filterwarnings statement work?

I'm in the process of upgrading a large Django project to the latest version of that framework. To help identify things that will soon be deprecated, I've begun running my unit tests with Python's -W argument:
python -Wa manage.py test classes.tests.test_file.TestFileClassIT.test_copy_all_files
When I run a test in this manner I get a lot of errors like this:
/srv/https/example.com/repo/classes/tests/test_file.py:30: ResourceWarning: unclosed file <_io.TextIOWrapper name='/var/www/example.com/photos/file.txt' mode='w' encoding='UTF-8'>
I would like Python to ignore all warnings of this type as I don't have time to go in and fix this in the hundreds of tests that triggers it. To do that, I discovered that the warnings package provides this capability so I've added it to one of the test modules to understand how it works:
# test_file.py
import unittest
import warnings
warnings.filterwarnings("ignore", message="ResourceWarning: unclosed file*")
class TestFileClassIT(unittest.TestCase):
def test_copy_all_files(self):
...
open("file1.txt", "w").close
...
However, I am still seeing the ResourceWarning in the output from my tests. I've read the documentation and this appears to be how to use the warnings module. I've also tried my warning without including the asterisk and the end of the warning string but that doesn't work either. What is the proper way to include this warning in my code so that it works properly?
On that specific error, inside your test function test_copy_all_files in your class TestFileClassIT
warnings.simplefilter('ignore', ResourceWarning)
On all errors, have you tried with inserting a simple entry into the list of warnings instead of filterwarnings?
warnings.simplefilter('ignore')
According to PEP-0565 on warnings system
if not sys.warnoptions:
warnings.simplefilter("ignore")

How can I silence RuntimeWarning on iteration speed when using Jupyter notebook with Python3 [duplicate]

I am working with code that throws a lot of (for me at the moment) useless warnings using the warnings library. Reading (/scanning) the documentation I only found a way to disable warnings for single functions. But I don't want to change so much of the code.
Is there a flag like python -no-warning foo.py?
What would you recommend?
Look at the Temporarily Suppressing Warnings section of the Python docs:
If you are using code that you know will raise a warning, such as a deprecated function, but do not want to see the warning, then it is possible to suppress the warning using the catch_warnings context manager:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
I don't condone it, but you could just suppress all warnings with this:
import warnings
warnings.filterwarnings("ignore")
Ex:
>>> import warnings
>>> def f():
... print('before')
... warnings.warn('you are warned!')
... print('after')
...
>>> f()
before
<stdin>:3: UserWarning: you are warned!
after
>>> warnings.filterwarnings("ignore")
>>> f()
before
after
There's the -W option.
python -W ignore foo.py
You can also define an environment variable (new feature in 2010 - i.e. python 2.7)
export PYTHONWARNINGS="ignore"
Test like this: Default
$ export PYTHONWARNINGS="default"
$ python
>>> import warnings
>>> warnings.warn('my warning')
__main__:1: UserWarning: my warning
>>>
Ignore warnings
$ export PYTHONWARNINGS="ignore"
$ python
>>> import warnings
>>> warnings.warn('my warning')
>>>
For deprecation warnings have a look at how-to-ignore-deprecation-warnings-in-python
Copied here...
From documentation of the warnings module:
#!/usr/bin/env python -W ignore::DeprecationWarning
If you're on Windows: pass -W ignore::DeprecationWarning as an argument to Python. Better though to resolve the issue, by casting to int.
(Note that in Python 3.2, deprecation warnings are ignored by default.)
Or:
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=DeprecationWarning)
import md5, sha
yourcode()
Now you still get all the other DeprecationWarnings, but not the ones caused by:
import md5, sha
Not to make it complicated, just use these two lines
import warnings
warnings.filterwarnings('ignore')
If you don't want something complicated, then:
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)
This is an old question but there is some newer guidance in PEP 565 that to turn off all warnings if you're writing a python application you should use:
import sys
import warnings
if not sys.warnoptions:
warnings.simplefilter("ignore")
The reason this is recommended is that it turns off all warnings by default but crucially allows them to be switched back on via python -W on the command line or PYTHONWARNINGS.
When all else fails use this: https://github.com/polvoazul/shutup
pip install shutup
then add to the top of your code:
import shutup; shutup.please()
Disclaimer: I am the owner of that repository. I wrote it after the 5th time I needed this and couldn't find anything simple that just worked.
If you know what are the useless warnings you usually encounter, you can filter them by message.
import warnings
#ignore by message
warnings.filterwarnings("ignore", message="divide by zero encountered in divide")
##part of the message is also okay
warnings.filterwarnings("ignore", message="divide by zero encountered")
warnings.filterwarnings("ignore", message="invalid value encountered")
import sys
if not sys.warnoptions:
import warnings
warnings.simplefilter("ignore")
Change ignore to default when working on the file or adding new functionality to re-enable warnings.
I realise this is only applicable to a niche of the situations, but within a numpy context I really like using np.errstate:
np.sqrt(-1)
__main__:1: RuntimeWarning: invalid value encountered in sqrt
nan
However, using np.errstate:
with np.errstate(invalid='ignore'):
np.sqrt(-1)
nan
The best part being you can apply this to very specific lines of code only.
More pythonic way to ignore WARNINGS
Since 'warning.filterwarnings()' is not suppressing all the warnings, i will suggest you to use the following method:
import logging
for name in logging.Logger.manager.loggerDict.keys():
logging.getLogger(name).setLevel(logging.CRITICAL)
#rest of the code starts here...
OR,
If you want to suppress only a specific set of warnings, then you can filter like this:
import logging
for name in logging.Logger.manager.loggerDict.keys():
if ('boto' in name) or ('urllib3' in name) or ('s3transfer' in name) or ('boto3' in name) or ('botocore' in name) or ('nose' in name):
logging.getLogger(name).setLevel(logging.CRITICAL)
#rest of the code starts here...
warnings are output via stderr and the simple solution is to append '2> /dev/null' to the CLI. this makes a lot of sense to many users such as those with centos 6 that are stuck with python 2.6 dependencies (like yum) and various modules are being pushed to the edge of extinction in their coverage.
this is especially true for cryptography involving SNI et cetera. one can update 2.6 for HTTPS handling using the proc at:
https://urllib3.readthedocs.io/en/latest/user-guide.html#ssl-py2
the warning is still in place, but everything you want is back-ported. the re-direct of stderr will leave you with clean terminal/shell output although the stdout content itself does not change.
responding to FriendFX. sentence one (1) responds directly to the problem with an universal solution. sentence two (2) takes into account the cited anchor re 'disable warnings' which is python 2.6 specific and notes that RHEL/centos 6 users cannot directly do without 2.6. although no specific warnings were cited, para two (2) answers the 2.6 question I most frequently get re the short-comings in the cryptography module and how one can "modernize" (i.e., upgrade, backport, fix) python's HTTPS/TLS performance. para three (3) merely explains the outcome of using the re-direct and upgrading the module/dependencies.

Unable to suppress deprecation warnings

In my Django application, when I import one third party library, I get this warning in the console:
the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
If however I do the import inside Python shell, then everything is ok. I want to achive the same behaviour in Django. This is what I've tried based on answers in other OS threads:
import warnings
from django.utils.deprecation import RemovedInDjango110Warning
warnings.filterwarnings(action="ignore", category=RemovedInDjango110Warning)
The above code results in another error message, that says that RemovedInDjango110Warning does not exists. I also tried this:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
from third_party_lib import some_module
But still I get the very same error message. So, it seems like all previous answers to this problem got outdated. And we need some fresh fix. Thanks!
I also tried this:
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore",category=DeprecationWarning)
from third_party_lib import some_module
But it has no effect.
There are a couple of issues with the code you've tried. If you want to filter PendingDeprecationWarning, then you should use PendingDeprecationWarning in your code. Your code is using DeprecationWarning and RemovedInDjango110Warning, which are different warnings. Secondly, the fxn() function in the docs is an example function that creates a warning. It doesn't make sense to include it in your code.
You can either filter all pending deprecation warnings
import warnings
warnings.simplefilter("ignore", category=PendingDeprecationWarning)
However this might hide pending deprecations in your own code that you should fix. A better approach would be to use a context manager, to filter out warnings when importing the third-party lib.
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=PendingDeprecationWarning)
from third_party_lib import some_module

How to ignore deprecation warnings in Python

I keep getting this :
DeprecationWarning: integer argument expected, got float
How do I make this message go away? Is there a way to avoid warnings in Python?
You should just fix your code but just in case,
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
I had these:
/home/eddyp/virtualenv/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/persisted/sob.py:12:
DeprecationWarning: the md5 module is deprecated; use hashlib instead import os, md5, sys
/home/eddyp/virtualenv/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-x86_64.egg/twisted/python/filepath.py:12:
DeprecationWarning: the sha module is deprecated; use the hashlib module instead import sha
Fixed it with:
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore",category=DeprecationWarning)
import md5, sha
yourcode()
Now you still get all the other DeprecationWarnings, but not the ones caused by:
import md5, sha
From documentation of the warnings module:
#!/usr/bin/env python -W ignore::DeprecationWarning
If you're on Windows: pass -W ignore::DeprecationWarning as an argument to Python. Better though to resolve the issue, by casting to int.
(Note that in Python 3.2, deprecation warnings are ignored by default.)
None of these answers worked for me so I will post my way to solve this. I use the following at the beginning of my main.py script and it works fine.
Use the following as it is (copy-paste it):
def warn(*args, **kwargs):
pass
import warnings
warnings.warn = warn
Example:
import "blabla"
import "blabla"
def warn(*args, **kwargs):
pass
import warnings
warnings.warn = warn
# more code here...
# more code here...
I found the cleanest way to do this (especially on windows) is by adding the following to C:\Python26\Lib\site-packages\sitecustomize.py:
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
Note that I had to create this file. Of course, change the path to python if yours is different.
Docker Solution
Disable ALL warnings before running the python application
You can disable your dockerized tests as well
ENV PYTHONWARNINGS="ignore::DeprecationWarning"
When you want to ignore warnings only in functions you can do the following.
import warnings
from functools import wraps
def ignore_warnings(f):
#wraps(f)
def inner(*args, **kwargs):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("ignore")
response = f(*args, **kwargs)
return response
return inner
#ignore_warnings
def foo(arg1, arg2):
...
write your code here without warnings
...
#ignore_warnings
def foo2(arg1, arg2, arg3):
...
write your code here without warnings
...
Just add the #ignore_warnings decorator on the function you want to ignore all warnings
Python 3
Just write below lines that are easy to remember before writing your code:
import warnings
warnings.filterwarnings("ignore")
If you are using logging (https://docs.python.org/3/library/logging.html) to format or redirect your ERROR, NOTICE, and DEBUG messages, you can redirect the WARNINGS from the warning system to the logging system:
logging.captureWarnings(True)
It will capture the warnings with the tag "py.warnings". Also if you want to throw away those warnings without logging, you can then, set the logging level to ERROR by using:
logging.getLogger("py.warnings").setLevel(logging.ERROR)
It will cause all those warnings to be ignored without showing up in your terminal or anywhere else.
See https://docs.python.org/3/library/warnings.html and https://docs.python.org/3/library/logging.html#logging.captureWarnings and captureWarnings set to True doesn't capture warnings
In my case, I was formatting all the exceptions with the logging system, but warnings (e.g. scikit-learn) were not affected.
Pass the correct arguments? :P
On the more serious note, you can pass the argument -Wi::DeprecationWarning on the command line to the interpreter to ignore the deprecation warnings.
Convert the argument to int. It's as simple as
int(argument)
For python 3, just write below codes to ignore all warnings.
from warnings import filterwarnings
filterwarnings("ignore")
Try the below code if you're Using Python3:
import sys
if not sys.warnoptions:
import warnings
warnings.simplefilter("ignore")
or try this...
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
or try this...
import warnings
warnings.filterwarnings("ignore")
If you know what you are doing, another way is simply find the file that warns you(the path of the file is shown in warning info), comment the lines that generate the warnings.
A bit rough, but it worked for me after the above methods did not.
./myscrypt.py 2>/dev/null
Not to beat you up about it but you are being warned that what you are doing will likely stop working when you next upgrade python. Convert to int and be done with it.
BTW. You can also write your own warnings handler. Just assign a function that does nothing.
How to redirect python warnings to a custom stream?
Comment out the warning lines in the below file:
lib64/python2.7/site-packages/cryptography/__init__.py

Categories