Python-Kontextmanager: Benutzerdefinierte mit Blöcken erstellen

Erfahren Sie, wie Sie benutzerdefinierte Kontextmanager in Python schreiben. Beherrschen Sie den Contextmanager-Dekorator und die Methoden __enter__/__exit__ für die Ressourcensicherheit.

Versuchen Sie es im Editor

Übersicht

Kontextmanager sind ein eleganter Mechanismus in Python, der für den Aufbau und Abbau externer Ressourcen entwickelt wurde. In der Software erfordern viele Vorgänge Aktionspaare: Öffnen und Schließen von Dateien, Herstellen und Trennen von Datenbanken oder Erfassen und Freigeben von Sperren. Wenn ein Programm nach dem Setup-Schritt, aber vor dem Teardown-Schritt abstürzt, bleiben diese Ressourcen im Speicher gesperrt. Kontextmanager gewährleisten, dass Ressourcen unter allen Umständen sicher bereinigt werden.

Die Standardmethode zum Aufrufen eines Kontextmanagers ist die Verwendung der „with“-Anweisung. Unter der Haube muss jedes Objekt, das in einer „with“-Anweisung verwendet wird, das Context Manager-Protokoll implementieren. Dieses Protokoll besteht aus zwei speziellen Methoden: „__enter__()“ und „__exit__()“. Wenn der „with“-Block beginnt, wird „__enter__()“ aufgerufen, um die Ressource vorzubereiten. Wenn der „with“-Block beendet wird oder eine Ausnahme auslöst, wird „__exit__()“ automatisch ausgelöst und erhält Informationen über jede ausgelöste Ausnahme, damit er die Bereinigung durchführen oder Fehler unterdrücken kann.

Bei einfachen Anwendungsfällen kann das Schreiben einer Klasse mit den Methoden „__enter__“ und „__exit__“ wortreich wirken. Um dies zu vereinfachen, stellt die Standardbibliothek von Python das Modul „contextlib“ bereit, das den Dekorator „@contextmanager“ enthält. Mit diesem Dekorator können Sie eine einfache Generatorfunktion schreiben, die eine einzelne „yield“-Anweisung enthält. Der Code vor dem „Yield“ fungiert als Setup, der Yield-Wert fungiert als Ressource und der Code nach dem „Yield“ stellt die Bereinigung dar. Durch die Beherrschung von Kontextmanagern wird sichergestellt, dass Ihre Anwendungen leckagefrei bleiben.

Code- und Ausführungsausgabe

Eine benutzerdefinierte Klasse, die __enter__ und __exit__ implementiert, um die Grenzen der Ausführungsprotokollierung zu verwalten.

context_managers.py
Versuchen Sie es im Editor
class CustomManager:
    def __enter__(self):
        print("--> Resource Setup: Entering the block")
        return "RESOURCE_KEY"

    def __exit__(self, exc_type, exc_value, traceback):
        print("<-- Resource Teardown: Exiting the block")
        if exc_type:
            print(f"Exception Intercepted: {exc_value}")
        return True  # Suppress exceptions

with CustomManager() as res:
    print(f"Working inside block with resource: {res}")
    # Force an error to verify exception handling
    x = 1 / 0
print("Program continues running safely.")
Terminal-Ausgabe
--> Resource Setup: Entering the block
Working inside block with resource: RESOURCE_KEY
<-- Resource Teardown: Exiting the block
Exception Intercepted: division by zero
Program continues running safely.

Schrittweise Umsetzung

  • Verwalten von Datenbanktransaktionen (Commit bei Erfolg, Rollback bei Fehler)
  • Erwerben und Freigeben von Thread-Sperren in Multithread-Code
  • Umleiten der Standardausgabe (stdout) während Unit-Test-Skripts

Häufig gestellte Fragen

Wie unterdrücke ich Ausnahmen in einem benutzerdefinierten Kontextmanager?

Durch die Rückgabe von True aus der __exit__-Methode. Wenn es „True“ zurückgibt, werden alle innerhalb des Blocks ausgelösten Ausnahmen unterdrückt.

Können Sie mehrere Kontextmanager in einer Anweisung kombinieren?

Ja, Sie können sie durch Kommas trennen, z. B. mit open('file1.txt') als f1, open('file2.txt') als f2:.

Verwandte Themen

Empfohlene Python-Ressourcen

Erweitern Sie Ihr Wissen mit zugehörigen interaktiven Tutorials, Spickzetteln und Codevergleichen.