warnings — Warnungen steuern¶
Quellcode: Lib/warnings.py
Warnmeldungen werden meist dann ausgegeben, wenn es sinnvoll ist, den Benutzer auf einen Zustand im Programm hinzuweisen, der es normalerweise nicht rechtfertigt, eine Ausnahme auszulösen und das Programm abzubrechen. Zum Beispiel kann man warnen wollen, wenn ein Programm ein veraltetes Modul verwendet.
In Python gibt man Warnungen aus, indem man die in diesem Modul definierte Funktion warn() aufruft. In C dient dazu PyErr_WarnEx(); Näheres steht unter Exception Handling.
Warnmeldungen gehen normalerweise nach sys.stderr, doch wie mit ihnen umgegangen wird, lässt sich frei einstellen: von „alle Warnungen übergehen“ bis „alle in Ausnahmen verwandeln“. Der Umgang kann sich nach der Warnkategorie, dem Text der Warnmeldung und der Stelle im Quelltext richten, an der sie ausgegeben wird. Wiederholungen derselben Warnung an derselben Quelltextstelle werden üblicherweise unterdrückt.
Die Steuerung von Warnungen läuft in zwei Stufen. Zuerst wird bei jeder Warnung entschieden, ob überhaupt eine Meldung ausgegeben werden soll. Soll sie ausgegeben werden, wird sie anschließend über einen vom Benutzer einstellbaren Einhängepunkt formatiert und ausgegeben.
Ob eine Warnmeldung ausgegeben wird, steuert der Warnfilter, eine Folge von Vergleichsregeln und Aktionen. Regeln fügt man dem Filter mit filterwarnings() hinzu; mit resetwarnings() setzt man ihn auf seinen Ausgangszustand zurück.
Die Ausgabe der Warnmeldungen übernimmt showwarning(), die sich überschreiben lässt. Die Standardausführung dieser Funktion formatiert die Meldung mit formatwarning(), die auch für eigene Umsetzungen zur Verfügung steht.
Siehe auch
Mit logging.captureWarnings() kannst du alle Warnungen über die normale Protokollierung abwickeln.
Warnkategorien¶
Es gibt eine Reihe eingebauter Ausnahmen, die für Warnkategorien stehen. Diese Einteilung ist nützlich, um ganze Gruppen von Warnungen herausfiltern zu können.
Technisch sind das eingebaute Ausnahmen, dokumentiert sind sie aber hier, weil sie dem Gedanken nach zum Warnmechanismus gehören.
Eigener Code kann weitere Warnkategorien festlegen, indem er von einer der Standardkategorien erbt. Eine Warnkategorie muss immer eine Unterklasse der Klasse Warning sein.
Derzeit sind die folgenden Warnkategorieklassen definiert:
Klasse |
Beschreibung |
|---|---|
Basisklasse für Warnkategorien. Sie ist eine Unterklasse von |
|
Basisklasse für Warnungen aus eigenem Code. Die Standardkategorie von |
|
Basisklasse für Warnungen über veraltete Features, wenn diese Warnungen für andere Python-Entwickler bestimmt sind. Sie wird standardmäßig übergangen, außer wenn Code in |
|
Basisklasse für Warnungen über Features, die künftig als veraltet gelten werden. Sie wird standardmäßig übergangen. |
|
Basisklasse für Warnungen über zweifelhafte Syntax. Sie entstehen meist beim Kompilieren von Python-Quellcode und lassen sich daher unter Umständen nicht durch Filter zur Laufzeit unterdrücken. |
|
Basisklasse für Warnungen bezüglich zweifelhaften Laufzeitverhaltens. |
|
Basisklasse für Warnungen über veraltete Features, wenn diese Warnungen für Endbenutzer von in Python geschriebenen Anwendungen bestimmt sind. |
|
Basisklasse für Warnungen, die beim Importieren eines Moduls ausgelöst werden. Sie wird standardmäßig übergangen. |
|
Basisklasse für Warnungen im Zusammenhang mit Unicode. |
|
Basisklasse für Warnungen im Zusammenhang mit Kodierungen. Näheres steht unter Opt-in EncodingWarning. |
|
Basisklasse für Warnungen im Zusammenhang mit |
|
Basisklasse für Warnungen im Zusammenhang mit der Nutzung von Ressourcen. Sie wird standardmäßig übergangen. |
Geändert in Version 3.7: Früher wurden DeprecationWarning und FutureWarning danach unterschieden, ob ein Feature ganz entfernt wurde oder sein Verhalten änderte. Jetzt unterscheiden sie sich danach, an wen sie sich richten und wie die Standard-Warnfilter mit ihnen umgehen.
Der Warnfilter¶
Der Warnfilter steuert, ob Warnungen übergangen, angezeigt oder in Fehler verwandelt werden, also eine Ausnahme auslösen.
Dem Gedanken nach führt der Warnfilter eine geordnete Liste von Filterangaben. Jede einzelne Warnung wird der Reihe nach mit jeder Filterangabe der Liste verglichen, bis eine passt. Der Filter bestimmt dann, wie mit dem Treffer umgegangen wird. Jeder Eintrag ist ein Tupel der Form (action, message, category, module, lineno) mit folgender Bedeutung:
action ist eine der folgenden Zeichenketten:
Wert
Behandlung
"default"gibt das erste Auftreten passender Warnungen für jede Stelle aus, an der die Warnung ausgegeben wird (Modul und Zeilennummer)
"error"verwandelt passende Warnungen in Ausnahmen
"ignore"gibt passende Warnungen nie aus
"always"gibt passende Warnungen immer aus
"all"anderer Name für „always“
"module"gibt das erste Auftreten passender Warnungen für jedes Modul aus, in dem die Warnung ausgegeben wird, unabhängig von der Zeilennummer
"once"gibt nur das erste Auftreten passender Warnungen aus, unabhängig von der Stelle
message ist eine Zeichenkette mit einem regulären Ausdruck, auf den der Anfang der Warnmeldung ohne Beachtung der Groß- und Kleinschreibung passen muss. Beginnt und endet message in
-WundPYTHONWARNINGSmit einem Schrägstrich (/), gibt es wie oben einen regulären Ausdruck an. Andernfalls ist es eine wörtliche Zeichenkette, auf die der Anfang der Warnmeldung ohne Beachtung der Groß- und Kleinschreibung passen muss, wobei Leerraum am Anfang und Ende von message übergangen wird.category ist eine Klasse, eine Unterklasse von
Warning. Die Warnkategorie muss eine Unterklasse davon sein, damit die Regel passt.module ist eine Zeichenkette mit einem regulären Ausdruck, auf den der Anfang des vollständig qualifizierten Modulnamens unter Beachtung der Groß- und Kleinschreibung passen muss. Beginnt und endet module in
-WundPYTHONWARNINGSmit einem Schrägstrich (/), gibt es wie oben einen regulären Ausdruck an. Andernfalls ist es eine wörtliche Zeichenkette, der der vollständig qualifizierte Modulname unter Beachtung der Groß- und Kleinschreibung gleichen muss, wobei Leerraum am Anfang und Ende von module übergangen wird.lineno ist eine ganze Zahl, der die Zeilennummer entsprechen muss, in der die Warnung auftrat, oder
0für alle Zeilennummern.
Da die Klasse Warning von der eingebauten Klasse Exception abgeleitet ist, wird eine Warnung zum Fehler, indem einfach category(message) ausgelöst wird.
Passt eine gemeldete Warnung auf keinen eingetragenen Filter, greift die Aktion „default“ – daher ihr Name.
Kriterien für das Unterdrücken wiederholter Warnungen¶
Die Filter, die wiederholte Warnungen unterdrücken, entscheiden nach den folgenden Kriterien, ob eine Warnung als Wiederholung gilt:
"default": Eine Warnung gilt nur dann als Wiederholung, wenn (message, category, module, lineno) alle gleich sind."module": Eine Warnung gilt als Wiederholung, wenn (message, category, module) gleich sind. Die Zeilennummer bleibt außer Betracht."once": Eine Warnung gilt als Wiederholung, wenn (message, category) gleich sind; Modul und Zeilennummer bleiben außer Betracht.
Warnfilter beschreiben¶
Der Warnfilter wird aus den Optionen -W auf der Befehlszeile des Python-Interpreters und aus der Umgebungsvariablen PYTHONWARNINGS aufgebaut. Der Interpreter legt die Argumente aller angegebenen Einträge unausgewertet in sys.warnoptions ab. Das Modul warnings wertet sie beim ersten Import aus. Ungültige Optionen werden übergangen, nachdem eine Meldung nach sys.stderr ausgegeben wurde.
Einzelne Warnfilter werden als Folge von Feldern angegeben, die durch Doppelpunkte getrennt sind:
action:message:category:module:line
Was die einzelnen Felder bedeuten, steht unter Der Warnfilter. Stehen mehrere Filter in einer Zeile, etwa bei PYTHONWARNINGS, werden sie durch Kommas getrennt, und später aufgeführte Filter haben Vorrang vor früheren. Sie werden von links nach rechts angewandt, und die zuletzt angewandten Filter gehen den früheren vor.
Gebräuchliche Warnfilter gelten entweder für alle Warnungen, für Warnungen einer bestimmten Kategorie oder für Warnungen aus bestimmten Modulen oder Paketen. Einige Beispiele:
default # Show all warnings (even those ignored by default)
ignore # Ignore all warnings
error # Convert all warnings to errors
error::ResourceWarning # Treat ResourceWarning messages as errors
default::DeprecationWarning # Show DeprecationWarning messages
ignore,default:::mymodule # Only report warnings triggered by "mymodule"
error:::mymodule # Convert warnings to errors in "mymodule"
Der Standard-Warnfilter¶
Standardmäßig richtet Python mehrere Warnfilter ein. Sie lassen sich durch die Befehlszeilenoption -W, die Umgebungsvariable PYTHONWARNINGS und Aufrufe von filterwarnings() übersteuern.
In gewöhnlichen Release-Builds hat der Standard-Warnfilter die folgenden Einträge, nach Vorrang geordnet:
default::DeprecationWarning:__main__
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::ResourceWarning
In einem Debug-Build ist die Liste der Standard-Warnfilter leer.
Geändert in Version 3.2: Neben PendingDeprecationWarning wird jetzt auch DeprecationWarning standardmäßig übergangen.
Geändert in Version 3.7: DeprecationWarning wird wieder standardmäßig angezeigt, wenn Code in __main__ sie unmittelbar auslöst.
Geändert in Version 3.7: BytesWarning steht nicht mehr in der Standard-Filterliste. Stattdessen wird sie über sys.warnoptions eingestellt, wenn -b zweimal angegeben wird.
Den Standardfilter übersteuern¶
Wer Anwendungen in Python schreibt, möchte seinen Benutzern vielleicht standardmäßig alle Warnungen auf Python-Ebene vorenthalten und sie nur bei Tests oder bei der Arbeit an der Anwendung anzeigen. Das Attribut sys.warnoptions, über das Filtereinstellungen an den Interpreter gehen, lässt sich als Anhaltspunkt dafür nutzen, ob Warnungen abgeschaltet werden sollen:
import sys
if not sys.warnoptions:
import warnings
warnings.simplefilter("ignore")
Wer Testläufer für Python-Code schreibt, sollte umgekehrt dafür sorgen, dass für den getesteten Code standardmäßig alle Warnungen angezeigt werden, etwa so:
import sys
if not sys.warnoptions:
import os, warnings
warnings.simplefilter("default") # Change the filter in this process
os.environ["PYTHONWARNINGS"] = "default" # Also affect subprocesses
Wer schließlich interaktive Shells schreibt, die Benutzercode in einem anderen Namensraum als __main__ ausführen, sollte dafür sorgen, dass Meldungen vom Typ DeprecationWarning standardmäßig sichtbar sind, etwa mit folgendem Code. user_ns ist dabei das Modul, in dem interaktiv eingegebener Code ausgeführt wird:
import warnings
warnings.filterwarnings("default", category=DeprecationWarning,
module=user_ns.get("__name__"))
Warnungen zeitweise unterdrücken¶
Verwendest du Code, von dem du weißt, dass er eine Warnung auslöst, etwa eine veraltete Funktion, willst die Warnung aber nicht sehen – auch dann nicht, wenn Warnungen ausdrücklich über die Befehlszeile eingestellt wurden –, kannst du sie mit dem Kontextmanager catch_warnings unterdrücken:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
Innerhalb des Kontextmanagers werden alle Warnungen einfach übergangen. So kannst du bekanntermaßen veralteten Code verwenden, ohne die Warnung zu sehen, und unterdrückst sie trotzdem nicht für anderen Code, dem die Verwendung veralteter Teile vielleicht nicht bewusst ist.
Bemerkung
Näheres dazu, wie sicher der Kontextmanager
catch_warningsbei gleichzeitiger Ausführung ist, wenn er in Programmen mit mehreren Threads oder mit async-Funktionen verwendet wird, steht unter Sicherheit der Kontextmanager bei gleichzeitiger Ausführung.
Warnungen testen¶
Um Warnungen aus Code zu testen, nimm den Kontextmanager catch_warnings. Mit ihm kannst du den Warnfilter zeitweise ändern, um dir das Testen zu erleichtern. So fängst du etwa alle ausgelösten Warnungen zum Prüfen ein:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
Mit error anstelle von always lässt sich auch erreichen, dass alle Warnungen zu Ausnahmen werden. Dabei ist zu beachten: Wurde eine Warnung wegen einer Regel once oder default schon einmal ausgelöst, ist sie unabhängig von den gesetzten Filtern nicht wieder zu sehen, solange die zugehörige Warnungsregistrierung nicht geleert wurde.
Beim Verlassen des Kontextmanagers wird der Warnfilter auf den Stand beim Betreten zurückgesetzt. Das verhindert, dass Tests den Warnfilter zwischen den Tests unerwartet verändern und zu unbestimmten Testergebnissen führen.
Bemerkung
Näheres dazu, wie sicher der Kontextmanager
catch_warningsbei gleichzeitiger Ausführung ist, wenn er in Programmen mit mehreren Threads oder mit async-Funktionen verwendet wird, steht unter Sicherheit der Kontextmanager bei gleichzeitiger Ausführung.
Testest du mehrere Operationen, die dieselbe Art von Warnung auslösen, ist es wichtig, so zu testen, dass sich bestätigt: Jede Operation löst eine neue Warnung aus. Lass die Warnungen etwa als Ausnahmen auslösen und prüfe, dass die Operationen Ausnahmen auslösen. Prüfe, dass die Warnungsliste nach jeder Operation weiter wächst, oder lösche vor jeder neuen Operation die vorherigen Einträge aus der Warnungsliste.
Code für neue Versionen von Abhängigkeiten anpassen¶
Warnkategorien, die vor allem Python-Entwickler angehen und nicht die Endbenutzer von in Python geschriebenen Anwendungen, werden standardmäßig übergangen.
Insbesondere gehört DeprecationWarning zu diesen standardmäßig übergangenen Warnungen, und zwar für jedes Modul außer __main__. Entwickler sollten ihren Code deshalb auch mit sichtbaren, sonst übergangenen Warnungen testen, um früh von künftigen API-Änderungen zu erfahren, die Code brechen – sei es in der Standardbibliothek oder in fremden Paketen.
Im Idealfall hat der Code eine passende Testsuite, und der Testläufer schaltet beim Testen von selbst alle Warnungen ein. Der Testläufer des Moduls unittest macht das so.
In weniger idealen Fällen lässt sich prüfen, ob eine Anwendung veraltete Schnittstellen verwendet: indem man dem Python-Interpreter -Wd übergibt, die Kurzform von -W default, oder in der Umgebung PYTHONWARNINGS=default setzt. Damit gilt für alle Warnungen die Standardbehandlung, auch für die standardmäßig übergangenen. Welche Aktion bei angetroffenen Warnungen greift, änderst du über das Argument von -W, etwa -W error. Was möglich ist, steht näher beim Flag -W.
Verfügbare Funktionen¶
- warnings.warn(message, category=None, stacklevel=1, source=None, *, skip_file_prefixes=())¶
Gibt eine Warnung aus, übergeht sie oder löst eine Ausnahme aus. Ist das Argument category angegeben, muss es eine Warnkategorieklasse sein; Vorgabe ist
UserWarning. message kann stattdessen auch eine Instanz vonWarningsein. Dann wird category übergangen undmessage.__class__verwendet, und der Meldungstext iststr(message). Diese Funktion löst eine Ausnahme aus, wenn der Warnfilter die betreffende Warnung in einen Fehler verwandelt. Das Argument stacklevel können Hüllfunktionen in Python so nutzen:def deprecated_api(message): warnings.warn(message, DeprecationWarning, stacklevel=2)
Damit bezieht sich die Warnung auf den Aufrufer von
deprecated_apiund nicht auf den Quelltext vondeprecated_apiselbst, denn das würde den Zweck der Warnmeldung verfehlen.Mit dem Schlüsselwortargument skip_file_prefixes gibst du an, welche Stapelrahmen beim Zählen der Stapelebenen übergangen werden. Das ist nützlich, wenn die Warnung immer an Aufrufstellen außerhalb eines Pakets erscheinen soll und ein festes stacklevel nicht auf alle Aufrufwege passt oder schwer zu pflegen ist. Angegeben werden muss ein Tupel von Zeichenketten. Sind Präfixe angegeben, wird stacklevel stillschweigend auf
max(2, stacklevel)gesetzt. Damit eine Warnung dem Aufrufer von außerhalb des aktuellen Pakets zugeschrieben wird, kannst du so schreiben:# example/lower.py _warn_skips = (os.path.dirname(__file__),) def one_way(r_luxury_yacht=None, t_wobbler_mangrove=None): if r_luxury_yacht: warnings.warn("Please migrate to t_wobbler_mangrove=.", skip_file_prefixes=_warn_skips) # example/higher.py from . import lower def another_way(**kw): lower.one_way(**kw)
Damit bezieht sich die Warnung auf die Aufrufstellen
example.lower.one_way()undexample.higher.another_way(), aber nur bei aufrufendem Code außerhalb des Paketsexample.source ist, falls angegeben, das zerstörte Objekt, das eine
ResourceWarningausgegeben hat.Geändert in Version 3.6: Der Parameter source wurde hinzugefügt.
Geändert in Version 3.12: skip_file_prefixes wurde hinzugefügt.
- warnings.warn_explicit(message, category, filename, lineno, module=None, registry=None, module_globals=None, source=None)¶
Das ist eine Schnittstelle auf niedriger Ebene zur Funktionsweise von
warn(). Meldung, Kategorie, Dateiname und Zeilennummer werden hier ausdrücklich übergeben, weitere Argumente nach Bedarf. message muss eine Zeichenkette und category eine Unterklasse vonWarningsein, oder message ist eine Instanz vonWarning. Dann wird category übergangen.module sollte, falls angegeben, der Modulname sein. Wird kein Modul übergeben, wird der reguläre Ausdruck für das Modul im Warnfilter gegen die Modulnamen geprüft, die aus den Pfadbestandteilen ab allen übergeordneten Verzeichnissen gebildet werden – dabei fallen
/__init__.py,.pyund unter Windows.pywweg –, sowie gegen den Dateinamen ohne.py. Lautet der Dateiname zum Beispiel'/path/to/package/module.py', wird gegen'path.to.package.module','to.package.module','package.module','module'und'/path/to/package/module'geprüft.registry sollte, falls angegeben, das Dictionary
__warningregistry__des Moduls sein. Wird keine Registrierung übergeben, gilt jede Warnung als erstes Auftreten. Die Filteraktionen"default","module"und"once"werden dann wie"always"behandelt.module_globals sollte, falls angegeben, der globale Namensraum des Codes sein, für den die Warnung ausgegeben wird. Dieses Argument dient dazu, Quelltext auch für Module anzuzeigen, die in ZIP-Dateien oder anderen Importquellen außerhalb des Dateisystems liegen.
source ist, falls angegeben, das zerstörte Objekt, das eine
ResourceWarningausgegeben hat.Geändert in Version 3.6: Der Parameter source wurde hinzugefügt.
Geändert in Version 3.15: Wird kein Modul übergeben, wird der reguläre Ausdruck des Filters gegen die aus dem Pfad gebildeten Modulnamen geprüft, nicht nur gegen den Pfad selbst.
- warnings.showwarning(message, category, filename, lineno, file=None, line=None)¶
Schreibt eine Warnung in eine Datei. Die Standardausführung ruft
formatwarning(message, category, filename, lineno, line)auf und schreibt die entstandene Zeichenkette nach file, standardmäßigsys.stderr. Du kannst diese Funktion durch jedes aufrufbare Objekt ersetzen, indem du eswarnings.showwarningzuweist. line ist eine Quelltextzeile, die in die Warnmeldung aufgenommen wird. Fehlt line, versuchtshowwarning(), die durch filename und lineno bezeichnete Zeile zu lesen.
- warnings.formatwarning(message, category, filename, lineno, line=None)¶
Formatiert eine Warnung auf die übliche Weise. Zurückgegeben wird eine Zeichenkette, die Zeilenumbrüche enthalten kann und mit einem Zeilenumbruch endet. line ist eine Quelltextzeile, die in die Warnmeldung aufgenommen wird. Fehlt line, versucht
formatwarning(), die durch filename und lineno bezeichnete Zeile zu lesen.
- warnings.filterwarnings(action, message='', category=Warning, module='', lineno=0, append=False)¶
Fügt einen Eintrag in die Liste der Warnfilterangaben ein. Standardmäßig kommt er nach vorne. Ist append wahr, kommt er ans Ende. Dabei werden die Typen der Argumente geprüft, die regulären Ausdrücke message und module kompiliert und als Tupel in die Liste der Warnfilter eingefügt. Passen zwei Einträge auf dieselbe Warnung, gehen die weiter vorne stehenden den späteren vor. Weggelassene Argumente erhalten einen Wert, der auf alles passt.
- warnings.simplefilter(action, category=Warning, lineno=0, append=False)¶
Fügt einen einfachen Eintrag in die Liste der Warnfilterangaben ein. Die Parameter bedeuten dasselbe wie bei
filterwarnings(), doch reguläre Ausdrücke sind nicht nötig: Der eingefügte Filter passt immer auf jede Meldung in jedem Modul, solange Kategorie und Zeilennummer passen.
- warnings.resetwarnings()¶
Setzt den Warnfilter zurück. Damit verfällt die Wirkung aller früheren Aufrufe von
filterwarnings(), auch die der Befehlszeilenoptionen-Wund der Aufrufe vonsimplefilter().
- @warnings.deprecated(message, /, *, category=DeprecationWarning, stacklevel=1)¶
Dekorator, der kennzeichnet, dass eine Klasse, eine Funktion oder eine Überladung veraltet ist.
Ist dieser Dekorator auf ein Objekt angewandt, können beim Verwenden des Objekts zur Laufzeit Warnungen über das Veralten ausgegeben werden. Auch statische Typprüfer geben bei Verwendung des veralteten Objekts einen Hinweis aus.
Verwendung:
from warnings import deprecated from typing import overload @deprecated("Use B instead") class A: pass @deprecated("Use g instead") def f(): pass @overload @deprecated("int support is deprecated") def g(x: int) -> int: ... @overload def g(x: str) -> int: ...
Die durch category angegebene Warnung wird zur Laufzeit ausgegeben, wenn veraltete Objekte verwendet werden: bei Funktionen beim Aufruf, bei Klassen beim Erzeugen einer Instanz und beim Anlegen von Unterklassen. Ist category gleich
None, wird zur Laufzeit keine Warnung ausgegeben. stacklevel bestimmt, wo die Warnung ausgegeben wird. Bei1, der Vorgabe, erscheint sie beim unmittelbaren Aufrufer des veralteten Objekts, bei höheren Werten weiter oben im Stapel. Das Verhalten statischer Typprüfer berührt keines der Argumente category und stacklevel.Die Meldung zum Veralten, die dem Dekorator übergeben wird, landet im Attribut
__deprecated__des dekorierten Objekts. Bei einer Überladung muss der Dekorator nach dem Dekorator@overloadstehen, damit das Attribut an der Überladung vorhanden ist, wietyping.get_overloads()sie zurückgibt.Added in version 3.13: Siehe PEP 702.
Verfügbare Kontextmanager¶
- class warnings.catch_warnings(*, record=False, module=None, action=None, category=Warning, lineno=0, append=False)¶
Ein Kontextmanager, der den Warnfilter und die Funktion
showwarning()kopiert und beim Verlassen wiederherstellt. Ist das Argument record gleichFalse, der Vorgabe, gibt der Kontextmanager beim BetretenNonezurück. Ist record gleichTrue, wird eine Liste zurückgegeben, die sich nach und nach mit den Objekten füllt, die eine eigene Funktionshowwarning()sieht. Diese unterdrückt zugleich die Ausgabe nachsys.stderr. Jedes Objekt in der Liste hat garantiert die folgenden Attribute:message: die Warnmeldung, eine Instanz vonWarningcategory: die Warnkategorie, eine Unterklasse vonWarningfilename: der Name der Datei, in der die Warnung auftrat (str)lineno: die Zeilennummer in der Datei (int)file: das für die Ausgabe verwendete Dateiobjekt, falls vorhanden, sonstNoneline: die Quelltextzeile, falls verfügbar, sonstNonesource: das ursprüngliche Objekt, das die Warnung erzeugt hat, falls verfügbar, sonstNonemodule: der Name des Moduls, in dem die Warnung auftrat (str), sonstNone
Geändert in Version 3.6: Das Attribut
sourcewurde hinzugefügt.Geändert in Version 3.15: Das Attribut
modulewurde hinzugefügt.Der Typ dieser Objekte ist nicht festgelegt und kann sich ändern. Garantiert ist nur, dass die genannten Attribute vorhanden sind.
Das Argument module nimmt ein Modul, das anstelle des beim Import von
warningszurückgegebenen Moduls verwendet wird und dessen Filter geschützt wird. Dieses Argument gibt es vor allem, um das Modulwarningsselbst zu testen.Ist das Argument action nicht
None, gehen die übrigen Argumente ansimplefilter(), als wäre sie unmittelbar beim Betreten des Kontexts aufgerufen worden.Was die Parameter category und lineno bedeuten, steht unter Der Warnfilter.
Bemerkung
Näheres dazu, wie sicher der Kontextmanager
catch_warningsbei gleichzeitiger Ausführung ist, wenn er in Programmen mit mehreren Threads oder mit async-Funktionen verwendet wird, steht unter Sicherheit der Kontextmanager bei gleichzeitiger Ausführung.Geändert in Version 3.11: Die Parameter action, category, lineno und append wurden hinzugefügt.
Sicherheit der Kontextmanager bei gleichzeitiger Ausführung¶
Wie sich der Kontextmanager catch_warnings verhält, hängt vom Flag sys.flags.context_aware_warnings ab. Ist das Flag wahr, verhält er sich sicher bei gleichzeitiger Ausführung, sonst nicht. Sicher bei gleichzeitiger Ausführung heißt: sowohl threadsicher als auch sicher innerhalb von asyncio-Koroutinen und Tasks verwendbar. Threadsicher heißt, dass das Verhalten in einem Programm mit mehreren Threads vorhersagbar ist. Bei free-threaded-Builds ist das Flag standardmäßig wahr, sonst falsch.
Ist das Flag context_aware_warnings falsch, verändert catch_warnings die globalen Attribute des Moduls warnings. Das ist in einem Programm mit gleichzeitiger Ausführung nicht sicher, also mit mehreren Threads oder mit asyncio-Koroutinen. Verwenden etwa zwei oder mehr Threads die Klasse catch_warnings zur selben Zeit, ist das Verhalten undefiniert.
Ist das Flag wahr, verändert catch_warnings keine globalen Attribute, sondern legt den neu eingerichteten Filterzustand in einer ContextVar ab. Eine Kontextvariable bietet threadlokalen Speicher und macht die Verwendung von catch_warnings threadsicher.
Auch der Parameter record des Kontexthandlers verhält sich je nach Wert des Flags anders. Ist record wahr und das Flag falsch, arbeitet der Kontextmanager so, dass er die Funktion showwarning() des Moduls ersetzt und später wiederherstellt. Das ist bei gleichzeitiger Ausführung nicht sicher.
Sind record und das Flag wahr, wird die Funktion showwarning() nicht ersetzt. Stattdessen zeigt ein internes Property in der Kontextvariablen an, dass aufgezeichnet wird. In diesem Fall wird die Funktion showwarning() beim Verlassen des Kontexthandlers nicht wiederhergestellt.
Das Flag context_aware_warnings lässt sich über die Befehlszeilenoption -X context_aware_warnings oder über die Umgebungsvariable PYTHON_CONTEXT_AWARE_WARNINGS setzen.
Bemerkung
Die meisten Programme, die ein threadsicheres Verhalten des warnings-Moduls wollen, werden wohl auch das Flag
thread_inherit_contextauf wahr setzen wollen. Dieses Flag bewirkt, dass vonthreading.Threaderzeugte Threads mit einer Kopie der Kontextvariablen des startenden Threads beginnen. Ist es wahr, gilt der voncatch_warningsin einem Thread eingerichtete Kontext auch für die von ihm gestarteten neuen Threads. Ist es falsch, beginnen neue Threads mit einer leeren Warnungs-Kontextvariablen, sodass eine durch einen Kontextmanagercatch_warningseingerichtete Filterung nicht mehr aktiv ist.
Geändert in Version 3.14: Das Flag sys.flags.context_aware_warnings wurde hinzugefügt, ebenso die Verwendung einer Kontextvariablen für catch_warnings, wenn das Flag wahr ist. Frühere Python-Versionen verhielten sich so, als wäre das Flag immer falsch.