比较自定义 warnings.showwarning 中的消息字符串

Comparing message strings in custom warnings.showwarning

当我看到非常具体的警告时,我正在尝试执行自定义操作。警告是带有消息 'Skipping SYSTEM_VARIABLE record'UserWarning。我希望所有其他警告,包括所有其他带有不同消息的 UserWarning 像往常一样传播并打印到 stderr

我能找到的唯一方法是用自定义实现替换 warnings.showwarning,如以下测试脚本所示:

import warnings

def showw(message, category, filename, lineno, file=None, line=None):
    print(message, category, filename, lineno, file, line, sep='|')
    print(message == 'Skipping SYSTEM_VARIABLE record')
    print(category == UserWarning)
    if category == UserWarning and message == 'Skipping SYSTEM_VARIABLE record':
        print('Doing a thing here')
    else:
        original(message, category, filename, lineno, file=file, line=line)

original = warnings.showwarning
warnings.showwarning = showw

warnings.warn('Skipping SYSTEM_VARIABLE record')

此脚本打印出以下输出:

Skipping SYSTEM_VARIABLE record|<class 'UserWarning'>|x.py|15|None|None
False
True
x.py:15: UserWarning: Skipping SYSTEM_VARIABLE record
  warnings.warn('Skipping SYSTEM_VARIABLE record')

我觉得这个输出令人惊讶,因为第一行表明消息实际上是 'Skipping SYSTEM_VARIABLE record',所以第二行应该是 Trueif 而不是 else 应该被执行。但是,由于某些原因,这两个字符串似乎并不相同。

为什么会这样?为什么 "custom action" print('Doing a thing here') 没有被触发?

我已尝试将脚本中出现的所有三个 'Skipping SYSTEM_VARIABLE record' 替换为 'a' 以消除打字错误的可能性。发生完全相同的结果。

我在 CentOS 7 服务器上的 Anaconda 2.4.0 上使用 Python 3.5.2,因此 str 与 unicode 应该不是问题。

发帖几分钟后凭直觉找出答案:

比较失败的原因是message不是字符串,而是实际的警告对象,其字符串表示(通过str)恰好只是警告消息。

额外的打印输出,print(type(message)) 证明了这一事实:

<class 'UserWarning'>

正确的比较是str(message) == 'Skipping SYSTEM_VARIABLE record'

我保留这个问题和答案的唯一原因是 warnings.showwarning 的文档中似乎没有任何内容来明确描述此行为。