Heim  >  Artikel  >  Backend-Entwicklung  >  So verwenden Sie Pythons with-Anweisung

So verwenden Sie Pythons with-Anweisung

王林
王林nach vorne
2023-05-25 17:22:061962Durchsuche

 Anweisungskörper (with-body): Der in die with-Anweisung eingeschlossene Codeblock ruft die enter()-Methode des Kontextmanagers auf, bevor der Anweisungskörper ausgeführt wird, und die exit()-Methode wird ausgeführt, nachdem der Anweisungskörper ausgeführt wurde.

 Hier gibt contextexpression ein Kontextmanagerobjekt zurück, das in der as-Klausel keinem Ziel zugewiesen ist. Wenn die as-Klausel angegeben ist, wird der Rückgabewert der _enter()-Methode des Kontextmanagers dem Ziel zugewiesen. (S). Ziel(e) können eine einzelne Variable oder ein von „()“ umschlossenes Tupel sein (es kann keine Liste von Variablen sein, die nur durch „“,“ getrennt sind, „()“ muss hinzugefügt werden).

 Python hat einige integrierte Objekte verbessert und Unterstützung für Kontextmanager hinzugefügt, die in Anweisungen wie dem automatischen Schließen von Dateien, dem automatischen Erfassen und Freigeben von Thread-Sperren usw. verwendet werden können. Angenommen, Sie möchten eine Datei bearbeiten, können Sie die with-Anweisung verwenden, um den folgenden Code zu erhalten:

 Listing 2. Verwenden Sie die with-Anweisung, um das Dateiobjekt

 mit open(r'somefileName') as somefile:

zu bedienen

 for line in somefile:

 print line

 # ...more code

 Die with-Anweisung wird hier verwendet. Unabhängig davon, ob während der Dateiverarbeitung eine Ausnahme auftritt, ist garantiert, dass das offene Dateihandle nach dem geschlossen wurde with-Anweisung wird ausgeführt. Wenn Sie das traditionelle Try/finally-Paradigma verwenden, sollten Sie Code ähnlich dem folgenden verwenden:  

Listing 3. Try/finally-Methode zum Betreiben von Dateiobjekten

 somefile = open(r'somefileName')

 try:

 for line in somefile:

 print line

 # ...more code finally:

 somefile.close()

 Im Vergleich dazu kann die Verwendung der with-Anweisung den Codierungsaufwand reduzieren. Zur Unterstützung des Kontextverwaltungsprotokolls wurden außerdem Module wie Threading, Dezimalzahl usw. hinzugefügt.

 PEP 0343 beschreibt die Implementierung der with-Anweisung. Der Ausführungsprozess der with-Anweisung ähnelt dem folgenden Codeblock:

 

Listing 4. With-Anweisungsausführungsprozess

  context_manager = context_expression

  exit = type(context_manager).__exit__

 value = type(context_manager). __enter__(context_manager)

  exc = True # True bedeutet normale Ausführung, auch wenn eine Ausnahme vorliegt, wird diese ignoriert; False bedeutet, dass die Ausnahme erneut ausgelöst wird und die Ausnahme behandelt werden muss

 try: try:

 target = value # Wenn die as-Klausel verwendet wird

with-body # Mit-body ausführen

  außer: # Während der Ausführung tritt eine Ausnahme auf

 exc = False

  # Wenn __exit__ True zurückgibt, wird die Ausnahme ignoriert; Wenn es False zurückgibt, wird die Ausnahme erneut ausgelöst

  # Ausnahmen werden vom äußeren Code behandelt

 if not exit(context_manager, *sys.exc_info()):

 raise

 finally:

  #Normal beenden, oder durch die break/continue/return-Anweisung im Anweisungskörper Exit

  # Oder ignorieren Sie die Ausnahme und beenden Sie

 if exc:

 exit(context_manager, None, None, None)

  # Gibt standardmäßig None zurück, None ist Wird in einem booleschen Kontext als Falsch angesehen

 Führen Sie context_expression aus, um den context_manager für die Kontextverwaltung zu generieren.

  Rufen Sie die enter()-Methode des Kontextmanagers auf; wenn die as-Klausel verwendet wird, weisen Sie den Rückgabewert der enter()-Methode dem/den Ziel(en) in der as-Klausel zu.

  

Ausführungsanweisungskörper mit Körper

  Unabhängig davon, ob während der Ausführung eine Ausnahme auftritt, wird die Methode „exit()“ des Kontextmanagers ausgeführt. Die Methode „exit()“ ist für die Durchführung von „Bereinigungs“-Arbeiten wie der Freigabe verantwortlich Ressourcen usw. Wenn während der Ausführung keine Ausnahme auftritt oder die Anweisung break/continue/return im Anweisungshauptteil ausgeführt wird, rufen Sie „exit(None, None, None)“ mit „None“ als Parameter auf. Wenn während der Ausführung eine Ausnahme auftritt, verwenden Sie sys.excinfo Die Ausnahme Information ist der Parameteraufruf _exit(exc_type, exc_value, exc_traceback).

 Wenn eine Ausnahme auftritt und „exit(type, value, Traceback)“ „False“ zurückgibt, wird die Ausnahme erneut ausgelöst und eine andere Anweisungslogik als „with“ wird zur Behandlung der Ausnahme verwendet. Dies ist auch eine gängige Praxis, wenn „True“ vorliegt zurückgegeben wird, wird die Ausnahme ignoriert. Dann wird die Ausnahme behandelt.

 

Benutzerdefinierter Kontextmanager

 Entwickler können Klassen anpassen, die das Kontextverwaltungsprotokoll unterstützen. Der benutzerdefinierte Kontextmanager muss die beiden für das Kontextverwaltungsprotokoll erforderlichen Methoden enter() und exit() implementieren:  contextmanager._enter(): Geben Sie den Laufzeitkontext des Kontextmanagers ein und rufen Sie ihn auf, bevor der Anweisungshauptteil ausgeführt wird. Die with-Anweisung weist den Rückgabewert der Methode dem Ziel in der as-Klausel zu, sofern einer angegeben ist.

 contextmanager._exit(exc_type, exc_value, exc_traceback): Verlassen Sie den Laufzeitkontext, der sich auf den Kontextmanager bezieht, und geben Sie einen booleschen Wert zurück, der angibt, ob die aufgetretene Ausnahme behandelt werden soll. Die Parameter geben die Ausnahme an, die den Exit-Vorgang verursacht hat. Wenn beim Exit keine Ausnahme auftritt, sind alle drei Parameter None. Wenn eine Ausnahme auftritt, kehren Sie zurück.

 True bedeutet, dass die Ausnahme nicht behandelt wird. Andernfalls wird die Ausnahme nach dem Verlassen der Methode erneut ausgelöst und von der Codelogik außerhalb der with-Anweisung behandelt. Wenn innerhalb dieser Methode eine Ausnahme ausgelöst wird, ersetzt sie die von der Anweisung im Anweisungskörper ausgelöste Ausnahme. Wenn Sie eine Ausnahme behandeln, lösen Sie die Ausnahme nicht explizit aus, d. h. Sie können die über die Parameter übergebene Ausnahme nicht erneut auslösen. Sie müssen lediglich den Rückgabewert auf False setzen. Der Kontextverwaltungscode erkennt dann, ob exit() die Ausnahme nicht behandeln konnte.

 Das Folgende ist ein einfaches Beispiel, das zeigt, wie man einen benutzerdefinierten Kontextmanager erstellt. Beachten Sie, dass der Kontextmanager Definitionen für die Methoden enter() und exit() bereitstellen muss. Das Fehlen einer dieser beiden Methoden führt zu einem AttributeError. Die with-Anweisung prüft zunächst, ob die Methode exit() bereitgestellt wird, und prüft dann, ob die Methode enter() vorhanden ist definiert ist.

  Angenommen, es gibt eine Ressource DummyResource. Diese Ressource muss vor dem Zugriff zugewiesen und nach der Verwendung freigegeben werden. Die Zuweisungsoperation kann in der Methode enter () platziert werden, und die Freigabeoperation kann in der Methode exit () platziert werden. Der Einfachheit halber werden nur Druckanweisungen verwendet, um den aktuellen Vorgang anzuzeigen, und es gibt keine tatsächliche Ressourcenzuweisung und -freigabe.

 Listing 5. Benutzerdefinierte Objekte, die die with-Anweisung unterstützen

 class DummyResource:

 def __init__(self, tag):

 self.tag = tag

 print 'Resource [%s]' % tag

def __enter__(self):

 print '[Enter %s]: Ressource zuweisen.' % self.tag

  return self # Verschiedene Objekte können zurückgegeben werden

  def __exit__(self, exc_type, exc_value, exc_tb):

print '[Exit %s]: Freie Ressource.' % self.tag

 if exc_tb is None:

 print '[Exit %s]: Ohne Ausnahme beendet.' % self.tag

 print ' [Exit %s]: Beendet mit ausgelöster Ausnahme.' % self.tag

  return False # Kann weggelassen werden, die Standardeinstellung None wird auch als False betrachtet

  Enter() in DummyResource gibt einen Verweis auf sich selbst zurück. Der Verweis kann der Zielvariablen in der as-Klausel zugewiesen werden; der Typ des Rückgabewerts kann entsprechend den tatsächlichen Anforderungen auf einen anderen Typ festgelegt werden und muss nicht das Kontextmanagerobjekt selbst sein.

 Die Variable exctb wird in der Methode „exit()“ erkannt. Wenn sie nicht „None“ ist, bedeutet dies, dass eine Ausnahme aufgetreten ist. Beachten Sie, dass die Ausnahme von der externen Codelogik behandelt werden muss. Der Standardrückgabewert ist None und wird in einer booleschen Umgebung ebenfalls als False angesehen. Da jedoch keine Ausnahme auftritt, sind die drei Parameter von _exit() None. Der Kontextverwaltungscode kann diese Situation erkennen und normal behandeln.

  Das Folgende greift auf DummyResource in der with-Anweisung zu:

 

Listing 6. Verwenden eines benutzerdefinierten Objekts, das die with-Anweisung unterstützt

 mit DummyResource('Normal'):

 print '[with-body] Ohne Ausnahmen ausführen .“ body! '

 Das Ausführungsergebnis der ersten with-Anweisung lautet wie folgt:

 

Listing 7. With-Anweisung 1-Ausführungsergebnis

 Ressource [Normal]

 [Enter Normal]: Ressource zuweisen.

 [with- body] Ohne Ausnahmen ausführen.

  [Exit Normal]: Freie Ressource.  [Exit Normal]: Ohne Ausnahme beendet.

  Es ist ersichtlich, dass während der normalen Ausführung der Anweisungskörper mit dem Körper zuerst ausgeführt wird und Anschließend wird die Methode „exit()“ ausgeführt, um die Ressourcen freizugeben.

 Das Ausführungsergebnis der zweiten with-Anweisung lautet wie folgt:

 

Listing 8. Ausführungsergebnis von With-Anweisung 2

 Ressource [With-Exception]

 [Enter With-Exception]: Ressource zuweisen.

 [with -body ] Mit Ausnahme ausführen.

 [Exit With-Exception]: Ressource freigeben. [Exit With-Exception]: Beendet mit ausgelöster Ausnahme.

 Traceback (letzter Aufruf zuletzt):

 Datei „G:/ demo", Zeile 20, in raise Exception

 Exception

 Es ist ersichtlich, dass, wenn eine Ausnahme im With-Body auftritt, With-Body nicht ausgeführt wurde, die Ressourcen jedoch garantiert freigegeben werden. Gleichzeitig ist Die generierte Ausnahme wird durch Code außerhalb der with-Anweisungslogik zur Erfassung der Verarbeitung verursacht.

 Sie können den Kontextmanager anpassen, um Ressourcen im Softwaresystem zu verwalten, z. B. Datenbankverbindungen, Zugriffskontrolle für gemeinsam genutzte Ressourcen usw. Die Python-Onlinedokumentation Writing Context Managers bietet ein einfaches Beispiel für einen Kontextmanager zum Verwalten von Datenbankverbindungen.

 contextlib-Modul

 Das contextlib-Modul stellt drei Objekte bereit: Decorator-Kontextmanager, verschachtelte Funktion und schließender Kontextmanager. Mit diesen Objekten können Sie vorhandene Generatorfunktionen oder -objekte umschließen und Unterstützung für das Kontextverwaltungsprotokoll hinzufügen, sodass Sie keinen Kontextmanager speziell zur Unterstützung der with-Anweisung schreiben müssen.

 Der Dekorator-Kontextmanager

 Der Kontextmanager wird zum Dekorieren der Generatorfunktion verwendet. Nachdem die Generatorfunktion dekoriert wurde, wird ein Kontextmanager zurückgegeben und seine Enter()- und Exit()-Methoden werden vom Kontextmanager anstelle des vorherigen Iterators bereitgestellt . Die dekorierte Generatorfunktion kann nur einen Wert erzeugen, andernfalls wird eine RuntimeError-Ausnahme ausgelöst; der generierte Wert wird dem Ziel in der as-Klausel zugewiesen, wenn die as-Klausel verwendet wird. Schauen wir uns ein einfaches Beispiel an.装. Listing 9. Der Decorator ContextManager verwendet Beispiele

aus contextLib importingManager

@contextManager

def demo ():

)

Print 'Code Bef Ore Yield-Statement Executes in __ENTER__ '

 yield '** * contextmanager demo ***'

 print 'Code, nachdem yield-statement in __exit__ ausgeführt wird'

 print '[Freie Ressourcen]'

 mit demo() als Wert:

 print 'Zugewiesener Wert: %s' %-Wert Die Ergebnisausgabe lautet wie folgt:

  Code nach Yield-Anweisung wird in __exit__ ausgeführt

  [Freie Ressourcen]

  Es ist ersichtlich, dass die Anweisung vor Yield in der Generatorfunktion in der Methode enter() ausgeführt wird und die Anweisung nach Yield in Exit( ) wird in ausgeführt und der von yield generierte Wert wird der Wertvariablen in der as-Klausel zugewiesen.

 Es ist zu beachten, dass der Kontextmanager nur das Schreiben von enter ()/exit () auslässt, aber nicht für die Realisierung der „Erfassung“ und „Bereinigung“ von Ressourcen verantwortlich ist. Die Operation „Erfassung“ muss vor der Ausbeute definiert werden Anweisung und „Reinigung“ „Die Operation muss nach der Yield-Anweisung definiert werden, damit die with-Anweisung diese Anweisungen ausführt, um Ressourcen zu erhalten/freizugeben, wenn die Methode enter()/exit() ausgeführt wird, also die erforderliche Logik Die Steuerung muss in der Generatorfunktion implementiert werden, auch wenn beim Ressourcenzugriff ein Fehler auftritt.

 

Funktion verschachtelt

  Nested kann mehrere Kontextmanager zusammen organisieren, um die Verwendung verschachtelter with-Anweisungen zu vermeiden.

 

Listing 11. verschachtelte Syntax

 with nested(A(), B(), C()) as (X, Y, Z):

  # with-body code here

  Ähnlich wie:

Listing 12. Verschachtelter Ausführungsprozess

 mit A() als Wenn nach dem Auftreten einer Ausnahme die Methode „exit()“ eines Kontextmanagers für die Ausnahmebehandlung „Falsch“ zurückgibt, erkennt der äußere Kontextmanager die Ausnahme nicht.

 Kontextmanager-Abschluss

 Die Implementierung des Abschlusses ist wie folgt:

 

Listing 13. Kontextmanagement-Abschlussimplementierung

 Klassenabschluss (Objekt):

 # Hilfedokument hier

 def. __in it__(self, thing ):

 self.thing = thing

  def __enter__(self):

  return self.thing

  def __exit__(self, *exc_info):

  self.thing.close()

  Der Kontextmanager wird umgebrochen Das Objekt wird der Zielvariablen der as-Klausel zugewiesen und es wird sichergestellt, dass das geöffnete Objekt nach der Ausführung von with-body geschlossen wird. Das vom schließenden Kontextmanager umschlossene Objekt muss die Definition der Methode close() bereitstellen, andernfalls wird während der Ausführung ein AttributeError gemeldet.

 

Listing 14. Passen Sie Objekte an, die das Schließen unterstützen Ressourcen beschaffen. '  def free (self):

print 'Alle erworbenen Ressourcen bereinigen.' Ressourcen verwenden'

 Die Ergebnisausgabe lautet wie folgt:

 

Listing 15. Das Ausgabeergebnis des benutzerdefinierten Abschlussobjekts

 Acquire Ressourcen.

 Ressourcen verwenden

 Alle erworbenen Ressourcen bereinigen.

 Das Schließen eignet sich zum Bereitstellen von close(). Implementierte Objekte wie Netzwerkverbindungen, Datenbankverbindungen usw. können auch die erforderlichen „Reinigungs“-Arbeiten für Ressourcen durchführen Schnittstelle close() beim Anpassen der Klasse.

Das obige ist der detaillierte Inhalt vonSo verwenden Sie Pythons with-Anweisung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen