Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering based on custom warning categories

In addition to pre-existing warning categories, users can define their own warning classes, such as in the code below:

$ cat mwe.py 
#!/usr/bin/env python3.5

import warnings
import pprint

class ObnoxiousWarning(UserWarning):
    pass

for i in range(3):
    print(i)
    warnings.warn("I don't like this.", ObnoxiousWarning)

When invoking Python, the -W flag controls how to filter warnings. But when I try to get it to ignore my freshly minted warning category, I'm told the filter is ignored:

$ python3.5 -W ignore::ObnoxiousWarning ./mwe.py
Invalid -W option ignored: unknown warning category: 'ObnoxiousWarning'
0
./mwe.py:11: ObnoxiousWarning: I don't like this.
  warnings.warn("I don't like this.", ObnoxiousWarning)
1
2

How can I use the commandline to insert a filter for custom warning categories (as opposed to all UserWarnings or filtering based on the warning message, which I can do)?

Edit 2018-11-29: See Issue 22543: -W option cannot use nonstandard categories

like image 956
gerrit Avatar asked Feb 27 '17 20:02

gerrit


People also ask

How do you filter warnings in Python?

Use the filterwarnings() Function to Suppress Warnings in Python. The warnings module handles warnings in Python. We can show warnings raised by the user with the warn() function. We can use the filterwarnings() function to perform actions on specific warnings.

What is DeprecationWarning in Python?

DeprecationWarning. Base category for warnings about deprecated features when those warnings are intended for other Python developers (ignored by default, unless triggered by code in __main__ ).

What is a runtime warning?

A RuntimeWarning is used to signal to the runtime framework that a non-fatal error has been encountered. Server startup will proceed as usual.

How do I enable warnings in Python?

showwarning(message, category, filename, lineno, file=None, line=None): This function Writes a warning to a file. simplefilter(action, category=Warning, lineno=0, append=False): This function adds a single entry into the warnings filter requirements list.


Video Answer


1 Answers

Some of the answers lie in python source code. Look at the _getcategory function: https://github.com/python/cpython/blob/3.5/Lib/warnings.py#L147

def _getcategory(category):
    import re
    if not category:
        return Warning
    if re.match("^[a-zA-Z0-9_]+$", category):
        try:
            cat = eval(category)
        except NameError:
            raise _OptionError("unknown warning category: %r" % (category,))
    else:
        i = category.rfind(".")
        module = category[:i]
        klass = category[i+1:]
        try:
            m = __import__(module, None, None, [klass])
        except ImportError:
            raise _OptionError("invalid module name: %r" % (module,))
        try:
            cat = getattr(m, klass)
        except AttributeError:
            raise _OptionError("unknown warning category: %r" % (category,))
    if not issubclass(cat, Warning):
        raise _OptionError("invalid warning category: %r" % (category,))
    return cat

Python tries to eval your category or to import it from module you specify in filter. And that will fail, unless you have your module in PYTHONPATH.

PYTHONPATH='<path_to_dir_where_mwe_located>' python -W ignore::mwe.ObnoxiousWarning

This way, if you import your module in python shell warning would be filtered as you wish. To use filter in commandline, you must define your warning in separate module, other than that you execute.

mwe.py

class ObnoxiousWarning(UserWarning):
    pass

entrypoint.py

#!/usr/bin/env python3.5

import warnings
import pprint

from mwe import ObnoxiousWarning

for i in range(3):
    print(i)
    warnings.warn("I don't like this.", ObnoxiousWarning)

And finally:

PYTHONPATH='<path_to_dir_where_mwe_located>' python -W ignore::mwe.ObnoxiousWarning ./entrypoint.py
0
1
2

I don't understand why defining separate module with warning works, but it is. May be someone will explain it.

like image 150
r_black Avatar answered Oct 07 '22 03:10

r_black