我使用的 "warnings" 模块对吗?

Am I using "warnings" module right?

我正在使用它来在解析配置文件时发出警告。执行此操作时可能会发生各种错误 - 有些是致命的,有些则不是。所有那些非致命错误不应该中断解析,但它们也不能逃过用户的注意。这是警告模块的用武之地。

我目前正在这样做(伪代码):

while parsing:
    try:
        get dictionary["token"]
    except KeyError:
        warnings.warn("Looks like your config file don't have that token")

这一切看起来可读且舒适,但消息看起来像这样:

C:\Users\Renae\Documents\test.py:3: UserWarning: Looks like your config file don't have that token
  warnings.warn("Looks like your config file don't have that token")

为什么打印了两次?我应该在发出警告之前进行某种初始化(例如日志记录模块)吗?标准文档没有这方面的教程(或者有吗?)。

警告与 print()、stdout 或 stderr 的区别是什么?

当你使用warnings模块时,第二次打印实际上是堆栈,你可以使用stacklevel参数控制你想要打印的层数。示例 -

import warnings
def warn():
    warnings.warn("Blah",stacklevel=2)

warn()

这个结果 -

a.py:6: UserWarning: Blah
  warn()

如果你将它设置为一个不存在的级别,在上面的例子中说 3 ,那么它不会打印堆栈,示例 -

def warn():
    warnings.warn("Blah",stacklevel=3)

结果-

sys:1: UserWarning: Blah

尽管如您所见,文件也更改为 sys:1 。您可能想在那里显示一个意义堆栈(对于发出警告的函数的调用者,可能类似于 stacklevel=2)。

另一种抑制这种情况的方法是使用 warnings.warn_explicit() 方法并手动传入文件名和行号(行号中不应包含任何实际代码,否则该代码将被打印),尽管我这样做不建议这个。


此外,是的,当使用 warnings 模块时,数据通常进入 sys.stderr ,但您也可以使用不同的函数轻松地将警告发送到不同的文件,例如 - warnings.showwarning()