Was ist der Python-Modus, um den Kontextmanager zu erben?

8

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:

%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.

%Vor%

Ich habe sogar darüber nachgedacht, so etwas zu tun: Das sieht nach einer gewissen Aufräumaktion wie eine gute Idee aus:

%Vor%

BEARBEITEN: Der Code wurde korrigiert.

    
user37203 02.07.2015, 16:06
quelle

3 Antworten

5

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.

    
User 02.07.2015 16:27
quelle
2

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%     
Dunes 02.07.2015 17:35
quelle
1

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.

    
Ming 02.07.2015 16:40
quelle