Aufruf __enter__ und __exit__ manuell
Habe ich gegoogelt aufrufen __enter__ manuell
aber mit kein Glück. So stellen wir uns vor, ich habe MySQL connector-Klasse, die verwendet __enter__
und __exit__
Funktionen (ursprünglich mit with
- Anweisung) eine Verbindung herstellen/trennen einer Datenbank.
Und wir haben eine Klasse, die verwendet 2 dieser Anschlüsse (zum Beispiel für Daten-sync). Hinweis: dies ist nicht mein real-life-Szenario, aber es scheint das einfachste Beispiel.
Einfachste Weg, um Sie alle zusammen arbeiten, ist die Klasse wie folgt aus:
class DataSync(object):
def __init__(self):
self.master_connection = MySQLConnection(param_set_1)
self.slave_connection = MySQLConnection(param_set_2)
def __enter__(self):
self.master_connection.__enter__()
self.slave_connection.__enter__()
return self
def __exit__(self, exc_type, exc, traceback):
self.master_connection.__exit__(exc_type, exc, traceback)
self.slave_connection.__exit__(exc_type, exc, traceback)
# Some real operation functions
# Simple usage example
with DataSync() as sync:
records = sync.master_connection.fetch_records()
sync.slave_connection.push_records(records)
Q: Ist es okay (da ist etwas falsch) zu nennen __enter__
/__exit__
manuell so?
Pylint 1.1.0 ausstellen nicht alle Warnungen auf diesem, noch habe ich gefunden, einen Artikel darüber (google-link in der beggining).
Ist und was über den Aufruf von:
try:
# Db query
except MySQL.ServerDisconnectedException:
self.master_connection.__exit__(None, None, None)
self.master_connection.__enter__()
# Retry
Ist das eine gute/schlechte Praxis? Warum?
- Ich würde sagen, es ist gut, zu sehen, wie wir sind alle Erwachsene hier, oder Sie könnte so etwas wie ExitStack, der die Berufung für Sie.
- Die __exit__ - Methode aufgerufen werden, die in der with-Anweisung auf jeden Fall nicht, so dass bei Aufruf dieser Methoden manuell, soweit ich weiß.
- Ich habe ein Beispiel für die Verwendung Beispiel... In sofern der Fall ist (ich glaube,) haben Sie es zu nennen manuell.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hinweis: Diese Antwort ist nicht ordnungsgemäß Konto für mögliche Fehler, wenn es mehrere Aufrufe an den zugrunde liegenden
__enter__
und__exit__
Methoden. Siehe Eric ' s Antwort für eine, die nicht damit umzugehen.Nein, es ist nichts falsch mit, dass. Es gibt sogar Orte in der standard-Bibliothek, die es tun. Wie die
multiprocessing
- Modul:Oder die
tempfile
- Modul:Die standard-Bibliothek Beispiele nicht aufrufen
__enter__
/__exit__
für zwei Objekte, aber wenn Sie haben ein Objekt, das verantwortlich für die Erstellung/Zerstörung der Kontext für mehrere Objekte statt nur einem,, Aufruf__enter__
/__exit__
für alle in Ordnung ist.Nur potenzielle gotcha ist ordnungsgemäß verarbeitet die Rückgabewerte der
__enter__
__exit__
Aufrufe für die Objekte, die Sie verwalten. Mit__enter__
, müssen Sie sicherstellen, dass Sie zurückgeben, wasstate
ist erforderlich für die Benutzer der wrapper-Objekt wieder aus derwith ... as <state>:
nennen. Mit__exit__
Sie müssen entscheiden, wenn Sie wollen, zu propagieren und jede Ausnahme, die aufgetreten sind, im Kontext (von RückgabeFalse
) oder unterdrücken (durch RücksendungTrue
). Ihre verwalteten Objekte könnten versuchen, es zu tun, so oder so, müssen Sie entscheiden, was Sinn macht, für die wrapper-Objekt.__enter__
/__exit__
für Sie alle ist gut" - Nein, es ist nicht, zumindest nicht ohne die Verwaltung mögliche Fehler auf dem Weg.Ihre erste Beispiel ist nicht eine gute Idee:
Was passiert, wenn
slave_connection.__enter__
wirft eine Ausnahme:master_connection
erwirbt seine Ressourceslave_connection
fehlDataSync.__enter__
propogates AusnahmeDataSync.__exit__
läuft nichtmaster_connection
ist nie aufgeräumt!Was passiert, wenn
master_connection.__exit__
eine exception wirft?DataSync.__exit__
frühzeitig beendetslave_connection
ist nie aufgeräumt!contextlib.ExitStack
hier helfen kann:Die gleichen Fragen:
Was passiert, wenn
slave_connection.__enter__
wirft eine Ausnahme:stack
bereinigtmaster_connection
Was passiert, wenn
master_connection.__exit__
eine exception wirft?slave_connection
wird gereinigt, bevor diese aufgerufen wirdOk, was passiert, wenn
slave_connection.__exit__
eine exception wirft?ExitStack
macht Sie sicher zu nennenmaster_connection.__exit__
was passiert mit der slave-VerbindungEs ist nichts falsch mit dem Aufruf
__enter__
direkt, aber wenn Sie benötigen, rufen Sie es auf mehr als ein Objekt, stellen Sie sicher, dass Sie richtig Aufräumen!contextlib.ExitStack
Dokumentation wurde Hinzugefügt, in3.3
, so an der Zeit dano ' s Genaueste, aber ich Stimme zu, dass für 3.3+ dies ist der richtige Weg, dies zu tun.contextlib2
backport für frühere Versionen! Noch bevor ExitStack, die Sie erreicht hätten, die Sicherheit mit einer gewissen Vorsicht versuchen/finallysbefore_request
undafter_request
? Zum Beispiel ruft__enter__
innenbefore_request
und__exit__
imafter_request
?after_request