Python lehrt uns, Objekte mit __enter__
und __exit__
zu bereinigen.
Was, wenn ich ein Objekt erstellen muss, das Objekte verwendet, müssen Kontextmanager verwenden? Stellen Sie sich folgendes vor:
Normalerweise würden sie als solche verwendet werden:
%Vor% Was auch immer passiert, db1
und db2
führen beide ihre __exit__
Funktion aus und bereinigen die Verbindung, Flush, etc.
Wenn ich all das in eine Klasse legen würde, wie würde ich es tun? Ist das richtig? Das ist natürlich nicht richtig, der Kontextmanager für db1
und db2
läuft am Ende des Blocks, wie in den Kommentaren angegeben.
Ich habe sogar darüber nachgedacht, so etwas zu tun: Das sieht nach einer gewissen Aufräumaktion wie eine gute Idee aus:
BEARBEITEN: Der Code wurde korrigiert.
Ich würde mit der zweiten Lösung gehen, aber auch Datenbankfehler behandeln:
%Vor% Der erste Aufruf von __exit__
in __enter__
wegen with
- so funktioniert nicht.
BEARBEITEN: Lesen Sie auch die Antwort von @Ming . In vielen Fällen ist es kürzer.
Die meisten Context Manager können einfach mit dem @contextmanager
Decorator geschrieben werden. Sie schreiben eine Funktion mit einer Rendite, bevor die Rendite Ihre "Enter" -Funktion ist und nach der Rendite Ihre "Exit" -Funktion ist. Aufgrund der Art, wie Generatoren implementiert werden, wenn eine Ausbeute in einer with-Anweisung ist, endet die with-Anweisung nicht bei der Ausbeute.
zB
%Vor%Ausgänge:
%Vor% Hängt davon ab, was Sie insgesamt erreichen möchten. Eine Möglichkeit besteht darin, die einzelnen Kontextmanager zu erstellen und sie dann mit der contextlib.nested . Dadurch erhalten Sie ein einzelnes Objekt, das sich wie Ihr Beispiel MyApp
verhält, aber die vorhandene Standardbibliothek DRY (Do not Repair Yourself) verwendet.
Tags und Links python class python-2.7 contextmanager