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

Warning

Basisklasse für Warnkategorien. Sie ist eine Unterklasse von Exception.

UserWarning

Basisklasse für Warnungen aus eigenem Code. Die Standardkategorie von warn().

DeprecationWarning

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 __main__ sie auslöst.

PendingDeprecationWarning

Basisklasse für Warnungen über Features, die künftig als veraltet gelten werden. Sie wird standardmäßig übergangen.

SyntaxWarning

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.

RuntimeWarning

Basisklasse für Warnungen bezüglich zweifelhaften Laufzeitverhaltens.

FutureWarning

Basisklasse für Warnungen über veraltete Features, wenn diese Warnungen für Endbenutzer von in Python geschriebenen Anwendungen bestimmt sind.

ImportWarning

Basisklasse für Warnungen, die beim Importieren eines Moduls ausgelöst werden. Sie wird standardmäßig übergangen.

UnicodeWarning

Basisklasse für Warnungen im Zusammenhang mit Unicode.

EncodingWarning

Basisklasse für Warnungen im Zusammenhang mit Kodierungen. Näheres steht unter Opt-in EncodingWarning.

BytesWarning

Basisklasse für Warnungen im Zusammenhang mit bytes und bytearray.

ResourceWarning

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 -W und PYTHONWARNINGS mit 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 -W und PYTHONWARNINGS mit 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 0 fü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_warnings bei 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_warnings bei 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 von Warning sein. Dann wird category übergangen und message.__class__ verwendet, und der Meldungstext ist str(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_api und nicht auf den Quelltext von deprecated_api selbst, 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() und example.higher.another_way(), aber nur bei aufrufendem Code außerhalb des Pakets example.

source ist, falls angegeben, das zerstörte Objekt, das eine ResourceWarning ausgegeben 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 von Warning sein, oder message ist eine Instanz von Warning. 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, .py und unter Windows .pyw weg –, 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 ResourceWarning ausgegeben 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äßig sys.stderr. Du kannst diese Funktion durch jedes aufrufbare Objekt ersetzen, indem du es warnings.showwarning zuweist. line ist eine Quelltextzeile, die in die Warnmeldung aufgenommen wird. Fehlt line, versucht showwarning(), 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 -W und der Aufrufe von simplefilter().

@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. Bei 1, 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 @overload stehen, damit das Attribut an der Überladung vorhanden ist, wie typing.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 gleich False, der Vorgabe, gibt der Kontextmanager beim Betreten None zurück. Ist record gleich True, wird eine Liste zurückgegeben, die sich nach und nach mit den Objekten füllt, die eine eigene Funktion showwarning() sieht. Diese unterdrückt zugleich die Ausgabe nach sys.stderr. Jedes Objekt in der Liste hat garantiert die folgenden Attribute:

  • message: die Warnmeldung, eine Instanz von Warning

  • category: die Warnkategorie, eine Unterklasse von Warning

  • filename: 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, sonst None

  • line: die Quelltextzeile, falls verfügbar, sonst None

  • source: das ursprüngliche Objekt, das die Warnung erzeugt hat, falls verfügbar, sonst None

  • module: der Name des Moduls, in dem die Warnung auftrat (str), sonst None

Geändert in Version 3.6: Das Attribut source wurde hinzugefügt.

Geändert in Version 3.15: Das Attribut module wurde 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 warnings zurückgegebenen Moduls verwendet wird und dessen Filter geschützt wird. Dieses Argument gibt es vor allem, um das Modul warnings selbst zu testen.

Ist das Argument action nicht None, gehen die übrigen Argumente an simplefilter(), 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_warnings bei 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_context auf wahr setzen wollen. Dieses Flag bewirkt, dass von threading.Thread erzeugte Threads mit einer Kopie der Kontextvariablen des startenden Threads beginnen. Ist es wahr, gilt der von catch_warnings in 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 Kontextmanager catch_warnings eingerichtete 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.