warnings.simplefilter("always") 不强制在 Python 2.7 中发出警告
warnings.simplefilter("always") is not forcing warnings to be made in Python 2.7
warnings.simplefilter('always')
似乎不会导致警告在 Python 2.7 中重复出现。好像和'once'
一样的效果。
我正在尝试测试一些发出警告的代码。有一半时间,我试图测试的警告已经发出,所以我的测试使用simplefilter()
来确保再次发出警告。这个问题只出现在Python 2.7。 The other versions all seem to work as expected.
我遵循了 Python 2.7 文档中的示例 https://docs.python.org/2/library/warnings.html#testing-warnings
该示例按原样工作,但如果我在测试代码之前添加对 fxn()
的调用,则不会引发警告并且 len(w) = 0
而不是 1
.
具体来说,
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
fxn()
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
预期的结果是运行结束没有输出。
Python 2.7.14 和 2.7.15 中的实际结果:
Traceback (most recent call last):
File "warntest.py", line 14, in <module>
assert len(w) == 1
AssertionError
更新:
我还发现在发出第一个警告后调用 warnings.resetwarnings()
不起作用。
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
fxn()
warnings.resetwarnings()
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
fxn()
结果:
Traceback (most recent call last):
File "warntest.py", line 15, in <module>
assert len(w) == 1
AssertionError
这绝对是 Python 2.7 的错误,但我根据 Tom 的建议实施了 work-around。变通方法导致我的单元测试针对 Python 2.7 发出大量警告,但它通过了。基本上,当 Python 主要版本为 2 时,我添加了
warnings.simplefilter('always')
在考试开始之前,我跳过了个人
warnings.simplefilter('ignore')
我在测试中发现了应该忽略的警告。
在第一次发出警告之前,我处于无法控制过滤器的情况。我需要做的解决方法是粉碎发出警告的记录。这存储在发出警告的模块中的 __warningregistry__
中。键是一个元组(警告字符串、警告类型、行号)。如果该值为 truthy,则将跳过警告;如果是假的或没有这样的密钥,它将被发行。实际上,警告模块似乎从来没有将其设置为任何不真实的东西。
因此,如果您在 module
中调用可能引发警告的内容,则必要的步骤是:
if sys.version_info[0:2] == (2,7) and hasattr(module, '__warningregistry__'):
for k in module.__warningregistry__.keys():
if k[0].startswith(
'Expected warning string') \
and k[1] is UserWarning:
del module.__warningregistry__[k]
break
warnings.simplefilter('always')
我承认这简直太糟糕了。
warnings.simplefilter('always')
似乎不会导致警告在 Python 2.7 中重复出现。好像和'once'
一样的效果。
我正在尝试测试一些发出警告的代码。有一半时间,我试图测试的警告已经发出,所以我的测试使用simplefilter()
来确保再次发出警告。这个问题只出现在Python 2.7。 The other versions all seem to work as expected.
我遵循了 Python 2.7 文档中的示例 https://docs.python.org/2/library/warnings.html#testing-warnings
该示例按原样工作,但如果我在测试代码之前添加对 fxn()
的调用,则不会引发警告并且 len(w) = 0
而不是 1
.
具体来说,
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
fxn()
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
预期的结果是运行结束没有输出。 Python 2.7.14 和 2.7.15 中的实际结果:
Traceback (most recent call last):
File "warntest.py", line 14, in <module>
assert len(w) == 1
AssertionError
更新:
我还发现在发出第一个警告后调用 warnings.resetwarnings()
不起作用。
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
fxn()
warnings.resetwarnings()
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
fxn()
结果:
Traceback (most recent call last):
File "warntest.py", line 15, in <module>
assert len(w) == 1
AssertionError
这绝对是 Python 2.7 的错误,但我根据 Tom 的建议实施了 work-around。变通方法导致我的单元测试针对 Python 2.7 发出大量警告,但它通过了。基本上,当 Python 主要版本为 2 时,我添加了
warnings.simplefilter('always')
在考试开始之前,我跳过了个人
warnings.simplefilter('ignore')
我在测试中发现了应该忽略的警告。
在第一次发出警告之前,我处于无法控制过滤器的情况。我需要做的解决方法是粉碎发出警告的记录。这存储在发出警告的模块中的 __warningregistry__
中。键是一个元组(警告字符串、警告类型、行号)。如果该值为 truthy,则将跳过警告;如果是假的或没有这样的密钥,它将被发行。实际上,警告模块似乎从来没有将其设置为任何不真实的东西。
因此,如果您在 module
中调用可能引发警告的内容,则必要的步骤是:
if sys.version_info[0:2] == (2,7) and hasattr(module, '__warningregistry__'):
for k in module.__warningregistry__.keys():
if k[0].startswith(
'Expected warning string') \
and k[1] is UserWarning:
del module.__warningregistry__[k]
break
warnings.simplefilter('always')
我承认这简直太糟糕了。