在Python中发出警告而不会中断程序


189

我正在尝试在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中使用assertRaises对其进行测试。


您想如何准确地通知用户?通过电子邮件还是短信?可能会导致这种情况,但是您需要具体说明。
aaronasterling

2
你为什么不只是print消息?
sje397

1
@ sje397的要点是,我希望能够通过unittest测试是否已引发警告。如果仅将消息打印出来,则无法通过unittest中的assertRaises来完成。
Tomas Novotny 2010年

Answers:


157

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


1
非常感谢你。然后如何使用unittest测试警告是否已引发?我不能再使用assertRaises()了。
Tomas Novotny,2010年

@Tomas Novotny,您可以捕获stdout和stderr,然后检查是否在其中找到了由警告发出的字符串。
小麦色的

15
@Tomas:我从未听说过要测试警告的愿望,但是有一个warnings.catch_warnings上下文管理器可以让您做到这一点。
SilentGhost 2010年

289
import warnings
warnings.warn("Warning...........Message")

请参阅python文档:此处


6
warnings.warn("blabla", DeprecationWarning)为发出的警告添加了一个类别
shadi 19'Dec

52

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

在之后import warnings,可以在生成警告时指定警告类。如果未指定,则UserWarning默认为字面值。

>>> 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


作为替代方法,尤其是对于独立应用程序,请考虑使用该logging模块。它可以记录级别为debuginfowarningerror等的消息。缺省情况下,级别为warning或更高级别的日志消息被打印到stderr。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.