根据自定义警告类别过滤
Filtering based on custom warning categories
除了预先存在的警告类别,用户还可以define their own warning classes,例如在下面的代码中:
$ 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时,-W
flag controls how to filter warnings。但是当我试图让它忽略我刚创建的警告类别时,我被告知过滤器被忽略了:
$ 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:参见 Issue 22543: -W option cannot use nonstandard categories
部分答案在 python 源代码中。查看 _getcategory 函数:
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 尝试评估您的类别或从您在过滤器中指定的模块导入它。这将失败,除非你的模块在 PYTHONPATH 中。
PYTHONPATH='<path_to_dir_where_mwe_located>' python -W ignore::mwe.ObnoxiousWarning
这样,如果您在 python shell 中导入模块,警告将按您的意愿过滤。
要在命令行中使用过滤器,您必须在单独的模块中定义您的警告,而不是您执行的模块。
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)
最后:
PYTHONPATH='<path_to_dir_where_mwe_located>' python -W ignore::mwe.ObnoxiousWarning ./entrypoint.py
0
1
2
我不明白为什么定义带有警告的单独模块有效,但确实如此。可能有人会解释一下。
除了预先存在的警告类别,用户还可以define their own warning classes,例如在下面的代码中:
$ 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时,-W
flag controls how to filter warnings。但是当我试图让它忽略我刚创建的警告类别时,我被告知过滤器被忽略了:
$ 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:参见 Issue 22543: -W option cannot use nonstandard categories
部分答案在 python 源代码中。查看 _getcategory 函数: 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 尝试评估您的类别或从您在过滤器中指定的模块导入它。这将失败,除非你的模块在 PYTHONPATH 中。
PYTHONPATH='<path_to_dir_where_mwe_located>' python -W ignore::mwe.ObnoxiousWarning
这样,如果您在 python shell 中导入模块,警告将按您的意愿过滤。 要在命令行中使用过滤器,您必须在单独的模块中定义您的警告,而不是您执行的模块。
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)
最后:
PYTHONPATH='<path_to_dir_where_mwe_located>' python -W ignore::mwe.ObnoxiousWarning ./entrypoint.py
0
1
2
我不明白为什么定义带有警告的单独模块有效,但确实如此。可能有人会解释一下。