pythonwarnings

How to assuredly suppress a DeprecationWarning in Python?


I believe this question was raised lots of times already but I have a specific use case where I can't solve the issue with many of the methods described on the web.

In one of my projects, I am using joblib library, and it shows DeprecationWarning because it uses imp library somewhere internally:

from sklearn.externals.joblib import Parallel, delayed

def main():
    xs = Parallel()(delayed(lambda x: x**2)(i) for i in range(1, 6))
    print(sum(xs))

if __name__ == '__main__':
    main()

I am trying to filter out warning with interpreter option -W but it doesn't help:

$ python -W ignore example.py                                                                                                                   
[...]/lib/python3.7/site-packages/sklearn/externals/joblib/externals/cloudpickle/cloudpickle.py:47:
DeprecationWarning: the imp module is deprecated in favour of importlib; 
see the module's documentation for alternative uses import imp
55

Also, I was trying an explicit filtering using warnings module but it is not helping also:

import warnings
warnings.simplefilter('ignore', category=DeprecationWarning)
from sklearn.externals.joblib import Parallel, delayed

def main():
    xs = Parallel()(delayed(lambda x: x**2)(i) for i in range(1, 6))
    print(sum(xs))

if __name__ == '__main__':
    main()

I had similar issues with matplotlib module and some other third-party libraries. Probably there are some other ways (i.e., env vars) but I don't understand why these solutions don't work.

Could anyone explain how the warnings system actually works in Python? It is possible that third-party libraries intentionally override client's warnings settings? I would say that this question is one of the most obscure topics for me.


Solution

  • Interesting enough, that even following @Alex's advice, I still have warnings output, like this:

    import warnings
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', category=DeprecationWarning)
        from sklearn.externals.joblib import Parallel, delayed
    
    def main():
        xs = Parallel()(delayed(lambda x: x**2)(i) for i in range(1, 6))
        print(sum(xs))
    
    if __name__ == '__main__':
        main()
    
    # $ python -W ignore example.py
    # [...]
    # DeprecationWarning: the imp module is deprecated in favour of importlib; 
    # see the module's documentation for alternative uses
    #  import imp
    # 55
    

    So eventually, I decided to do it in a very hacky way and disable all warnings because I am bit tired of looking for a proper way to deal with them. (Not only for this library, but for many others that seem to be very eager about bombarding you with non-suppressible warnings).

    import warnings
    def noop(*args, **kargs): pass
    warnings.warn = noop
    from sklearn.externals.joblib import Parallel, delayed
    
    def main():
        xs = Parallel()(delayed(lambda x: x**2)(i) for i in range(1, 6))
        print(sum(xs))
    
    if __name__ == '__main__':
        main()
    

    If I use @Alex's advice wrongly or some of you have a better solution, I would be glad to accept it as an answer.


    Update 1

    Ok, it seems that it is pretty hard to influence the warnings, raised somewhere internally in the package. So probably the most simple thing would be to just replace warnings.warn with noop, or maybe somehow import the internal dependencies in advance and suppress them with a context manager.


    Update 2

    Some time ago, I found one more possible way to deal with warnings. You can redirect them into logging. In case no logger is explicitly configured, these warnings are essentially suppressed. It works for Jupyter and some libraries I've tested.

    import logging
    logging.captureWarnings(True)