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

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

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

I am trying to raise a Warning in Python without making the program crash / stop / interrupt.

I use the following simple function to check if the user passed a non-zero number to it. If so, the program should warn them, but continue as per normal. It should work like the code below, but should use class Warning(), Error() or Exception() instead of printing the warning out manually.

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

If I use the code below and pass 0 to the function, the program crashes and the value is never returned. Instead, I want the program to continue normally and just inform the user that he passed 0 to the function.

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

I want to be able to test that a warning has been thrown testing it by unittest. If I simply print the message out, I am not able to test it with assertRaises in unittest.


回答 0

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

You shouldn’t raise the warning, you should be using warnings module. By raising it you’re generating error, rather than warning.


回答 1

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

请参阅python文档:此处

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

See the python documentation: here


回答 2

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

在之后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 default, unlike an exception, a warning doesn’t interrupt.

After import warnings, it is possible to specify a Warnings class when generating a warning. If one is not specified, it is literally UserWarning by default.

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

To simply use a preexisting class instead, e.g. DeprecationWarning:

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

Creating a custom warning class is similar to creating a custom exception class:

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

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

For testing, consider assertWarns or assertWarnsRegex.


As an alternative, especially for standalone applications, consider the logging module. It can log messages having a level of debug, info, warning, error, etc. Log messages having a level of warning or higher are by default printed to stderr.