Warnung in Python auslösen, ohne das Programm zu unterbrechen

186

Ich versuche, eine Warnung in Python auszulösen, ohne dass das Programm abstürzt / stoppt / unterbricht.

Ich benutze die folgende einfache Funktion, um zu überprüfen, ob der Benutzer eine Zahl ungleich Null an ihn übergeben hat. In diesem Fall sollte das Programm sie warnen, aber wie gewohnt fortfahren. Es sollte unter wie der Code arbeitet, soll aber Klasse verwenden Warning(), Error()oder Exception()stattdessen die Warnung auszudrucken manuell.

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

Wenn ich den folgenden Code verwende und 0 an die Funktion übergebe, stürzt das Programm ab und der Wert wird nie zurückgegeben. Stattdessen möchte ich, dass das Programm normal fortgesetzt wird und den Benutzer darüber informiert, dass er 0 an die Funktion übergeben hat.

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

Ich möchte in der Lage sein zu testen, ob eine Warnung ausgelöst wurde, indem ich sie von unittest teste. Wenn ich die Nachricht einfach ausdrucke, kann ich sie nicht mit assertRaises in unittest testen.

Tomas Novotny
quelle
Wie genau möchten Sie den Benutzer benachrichtigen? per E-Mail oder SMS? Ursache, die angeschlossen werden kann, aber Sie müssen spezifisch sein.
Aaronasterling
2
Warum nicht nur printdie Nachricht?
sje397
1
@ sje397 Der Punkt ist, dass ich in der Lage sein möchte zu testen, dass eine Warnung ausgelöst wurde, indem ich sie von unittest teste. Wenn ich die Nachricht einfach ausdrucke, kann ich das mit assertRaises nicht in unittest tun.
Tomas Novotny

Antworten:

157

Sie sollten nicht raisedie Warnung, Sie sollten warningsModul verwenden. Indem Sie es auslösen, generieren Sie eher Fehler als Warnungen.

SilentGhost
quelle
1
Vielen Dank. Und wie teste ich dann, ob die Warnung mit unittest ausgelöst wurde? Ich kann assertRaises () nicht mehr verwenden.
Tomas Novotny
@Tomas Novotny Sie können stdout und stderr erfassen und dann überprüfen, ob die von Ihrer Warnung ausgegebenen Zeichenfolgen darin enthalten sind.
Wheaties
15
@Tomas: Ich habe noch nie von dem Wunsch gehört, auf Warnung zu testen, aber es gibt einen warnings.catch_warningsKontextmanager, mit dem Sie dies tun können.
SilentGhost
284
import warnings
warnings.warn("Warning...........Message")

Siehe die Python-Dokumentation: hier

Nekromant
quelle
4
Und warnings.warn("blabla", DeprecationWarning)für das Hinzufügen einer Klasse zu der Art von Warnung, die ausgegeben wird
Shadi
50

Im Gegensatz zu einer Ausnahme wird eine Warnung standardmäßig nicht unterbrochen.

Danach import warningskann beim Generieren einer Warnung eine Warnings- Klasse angegeben werden. Wenn eines nicht angegeben ist, ist es buchstäblich UserWarningstandardmäßig.

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

Um stattdessen einfach eine bereits vorhandene Klasse zu verwenden, z DeprecationWarning.

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

Das Erstellen einer benutzerdefinierten Warnklasse ähnelt dem Erstellen einer benutzerdefinierten Ausnahmeklasse:

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

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

Betrachten Sie zum Testen assertWarnsoder assertWarnsRegex.


Als Alternative, insbesondere für eigenständige Anwendungen, sollten Sie das loggingModul in Betracht ziehen . Es kann Nachrichten mit einer Debug- , Info- , Warn- , Fehlerstufe usw. protokollieren . Protokollnachrichten mit einer Warnstufe oder höher werden standardmäßig auf stderr gedruckt.

Scharfsinn
quelle