Filtering based on custom warning categories
除了预先存在的警告类别,用户还可以定义自己的警告类,例如在下面的代码中:
1 2 3 4 5 6 7 8 9 10 11 12 | $ 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) |
调用Python时,
1 2 3 4 5 6 7 | $ 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 |
如何使用命令行为自定义警告类别插入过滤器(与所有UserWarnings相反或基于警告消息进行过滤,我可以这样做)?
编辑2018-11-29:请参见问题22543:-W选项不能使用非标准类别
一些答案在于python源代码。 看看_getcategory函数:
https://github.com/python/cpython/blob/3.5/Lib/warnings.py#L147
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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会尝试评估您的类别或从您在过滤器中指定的模块中导入它。 这将失败,除非你的模块在PYTHONPATH中。
1 | PYTHONPATH='<path_to_dir_where_mwe_located>' python -W ignore::mwe.ObnoxiousWarning |
这样,如果您在python shell中导入模块,则会根据需要过滤警告。
要在命令行中使用过滤器,必须在单独的模块中定义警告,而不是在执行时。
mwe.py
1 2 | class ObnoxiousWarning(UserWarning): pass |
entrypoint.py
1 2 3 4 5 6 7 8 9 10 | #!/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) |
最后:
1 2 3 4 | PYTHONPATH='<path_to_dir_where_mwe_located>' python -W ignore::mwe.ObnoxiousWarning ./entrypoint.py 0 1 2 |
我不明白为什么定义单独的模块与警告工作,但它是。 可能有人会解释它。