在不中断程序的情况下在 Python 中引发警告

Raise warning in Python without interrupting program

提问人:Tomas Novotny 提问时间:10/8/2010 最后编辑:pfabriTomas Novotny 更新时间:5/18/2022 访问量:303809

问:

我试图在不使程序崩溃/停止/中断的情况下在 Python 中发出警告。

我使用以下简单函数来检查用户是否向它传递了一个非零数字。如果是这样,程序应该警告他们,但照常继续。它应该像下面的代码一样工作,但应该使用 class ,或者而不是手动打印警告。Warning()Error()Exception()

def is_zero(i):
   if i != 0:
     print "OK"
   else:
     print "WARNING: the input is 0!"
   return i

如果我使用下面的代码并将 0 传递给函数,程序会崩溃并且永远不会返回值。相反,我希望程序正常继续,并通知用户他将 0 传递给函数。

def is_zero(i):
   if i != 0:
     print "OK"
   else:
     raise Warning("the input is 0!")
   return i

我希望能够测试是否已通过 unittest 测试警告。如果我只是简单地打印出消息,则无法在 unittest 中使用 assertRaise 对其进行测试。

Python 异常 错误处理 警告

评论

1赞 aaronasterling 10/8/2010
您究竟希望如何通知用户?通过电子邮件或短信?因为可以连接,但你需要具体。
3赞 sje397 10/8/2010
你为什么不只传达信息呢?print
5赞 Tomas Novotny 10/8/2010
@sje397 关键是我希望能够测试是否已经抛出警告,通过 unittest 对其进行测试。如果我只是简单地打印出消息,则无法在 unittest 中使用 assertRaise 执行此操作。

答:

257赞 SilentGhost 10/8/2010 #1

你不应该使用警告,你应该使用警告模块。通过引发它,您正在生成错误,而不是警告。raise

评论

1赞 Tomas Novotny 10/8/2010
谢谢。那么,我如何使用 unittest 测试是否抛出了警告呢?我不能再使用 assertRaises() 了。
0赞 wheaties 10/8/2010
@Tomas Novotny 中,您可以捕获 stdout 和 stderr,然后检查是否在其中找到警告发出的字符串。
25赞 SilentGhost 10/8/2010
@Tomas:我从未听说过测试警告的愿望,但有一个可用的warnings.catch_warnings上下文管理器可以让你这样做。
1赞 eric 12/3/2021
@SilentGhost 如果它在你的代码中,你想测试它,不是吗?docs.pytest.org/en/6.2.x/warnings.html#warns(尽管公平地说,该评论已有 10 多年的历史)
1赞 Gulzar 4/28/2022
这并不能解释实际该怎么做。应该是公认的答案。
559赞 necromancer 10/8/2010 #2
import warnings
warnings.warn("Warning...........Message")

请参阅 python 文档:此处

评论

46赞 Shadi 12/30/2019
以及将类添加到发出的警告类型中warnings.warn("blabla", DeprecationWarning)
114赞 Asclepius 3/24/2018 #3

默认情况下,与异常不同,警告不会中断。

之后,可以在生成警告时指定 Warnings 类。如果未指定,则默认情况下,它实际上是 UserWarningimport warnings

>>> warnings.warn('This is a default warning.')
<string>:1: UserWarning: This is a default warning.

简单地使用预先存在的类,例如 DeprecationWarning

>>> warnings.warn('This is a particular warning.', DeprecationWarning)
<string>:1: DeprecationWarning: This is a particular warning.

创建自定义警告类类似于创建自定义异常类:

>>> class MyCustomWarning(UserWarning):
...     pass
... 
... warnings.warn('This is my custom warning.', MyCustomWarning)

<string>:1: MyCustomWarning: This is my custom warning.

对于测试,请考虑 assertWarnsassertWarnsRegex


作为替代方案,特别是对于独立应用程序,请考虑使用该模块。它可以记录具有调试信息警告错误等级别的消息。默认情况下,具有警告级别或更高级别的日志消息将打印到 stderr。logging

7赞 Markus Dutschke 5/18/2022 #4

只是一个小小的演示片段

我有点困惑如何使用,所以我在这里提供了一个简短的演示。注意 print(“warning 后运行的代码”) 是如何执行/不执行的。此外,warnings.warn 仅打印一次警告消息。warnings.warnwarnings.warnraise UserWarning

>>> import warnings
>>> 
>>> warnings.warn("test warning"); print("code running after warning")
<stdin>:1: UserWarning: test warning
code running after warning
>>> 
>>> raise UserWarning('test warning'); print("code running after warning")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UserWarning: test warning
>>> 
>>> warnings.warn("test warning"); print("code running after warning")
code running after warning

评论

0赞 Foxy Fox 8/8/2022
第一种情况和第三种情况有什么区别?为什么有不同的输出?
3赞 Markus Dutschke 8/8/2022
它们是一样的。因此,在第三种情况下,警告在过去已经提出