Frage

Ich bin neu in diesem, und ich versuche, nur die with Aussage zu verstehen. Ich verstehe, dass es soll den try / except Block ersetzen.

Jetzt nehme ich etwas tun, wie folgt aus:

try:
   name='rubicon'/2 # to raise an exception
except Exception as e:
   print "no not possible"
finally:
   print "Ok I caught you"

Wie ersetze ich dies mit einem Kontext-Manager?

War es hilfreich?

Lösung

with nicht wirklich ersetzen try / except, sondern vielmehr try / finally. Dennoch Sie können einen Kontext-Manager machen etwas anderes in Ausnahmefällen von Nicht-Ausnahme diejenigen:

class Mgr(object):
    def __enter__(self): pass
    def __exit__(self, ext, exv, trb):
        if ext is not None: print "no not possible"
        print "OK I caught you"
        return True

with Mgr():
    name='rubicon'/2 #to raise an exception

Der return True Teil ist, wo der Kontext-Manager die Ausnahme zu unterdrücken entscheidet (wie Sie tun, indem Sie nicht in Ihrer except Klausel Wiederbeschaffung).

Andere Tipps

Die contextlib.contextmanager Funktion Dekorateur bietet eine praktische Möglichkeit, ohne die Notwendigkeit, einen Kontextmanager der Bereitstellung eines vollwertigen ContextManager Klasse der eigenen (mit __enter__ und __exit__ Methoden zu schreiben, so dass Sie die Argumente für die __exit__ Methode nicht merken müssen, oder dass die __exit__ Methode muss, um die Ausnahme zu unterdrücken) return True. Stattdessen schreiben Sie eine Funktion mit einem einzigen yield an der Stelle, die with Block ausgeführt werden soll, und Sie Trap-Ausnahmen (das effektiv aus dem yield kommen), wie Sie normalerweise tun würde.

from contextlib import contextmanager
@contextmanager
def handler():
    # Put here what would ordinarily go in the `__enter__` method
    # In this case, there's nothing to do
    try:
        yield # You can return something if you want, that gets picked up in the 'as'
    except Exception as e:
        print "no not possible"
    finally:
        print "Ok I caught you"

with handler():
    name='rubicon'/2 #to raise an exception

geht Warum die zusätzliche Mühe einen Kontext Manager schreiben? Code wiederverwenden. Sie können die gleichen Kontext-Manager an mehreren Stellen verwenden, ohne die Ausnahmebehandlung zu duplizieren. Wenn die Ausnahmebehandlung zu dieser Situation eindeutig ist, dann nicht mit einem Kontext-Manager stören. Aber wenn das gleiche Muster taucht immer wieder (oder wenn es könnte für die Benutzer, zum Beispiel eine Datei zu schließen, einen Mutex Entriegeln), es lohnt sich die zusätzliche Mühe. Es ist auch ein ordentlich Muster zu verwenden, wenn die Ausnahmebehandlung ein wenig kompliziert ist, da es die Ausnahme von der Hauptcodezeile Fluss Handhabung trennt.

Die with in Python ist zum Einwickeln einer Reihe von Anweisungen bestimmt, in denen Sie und zerstören oder in der Nähe Ressourcen setzen soll. Es ist in ähnlicher Weise wie try...finally in dieser Hinsicht als die finally-Klausel wird selbst nach einer Ausnahme ausgeführt werden.

Ein Kontext-Manager ist ein Ziel, dass implementiert zwei Methoden: __enter__ und __exit__. Diese werden genannt unmittelbar vor und nach (jeweils) der with Block.

Nehmen Sie zum Beispiel einen Blick auf dem klassischen open() Beispiel:

with open('temp.txt', 'w') as f:
    f.write("Hi!")

Öffnen gibt ein File Objekt, das Gerät __enter__ mehr oder weniger wie return self und __exit__ wie self.close().

Die Komponenten von Context-Manager

  1. Sie sollten eine implementieren __ __ eingeben Methode, dass ein Objekt zurückgegeben
  2. Implementieren Sie eine __ __ Ausfahrt Methode.

Beispiel

Ich werde ein einfaches Beispiel geben, Ihnen zu zeigen, warum wir einen Kontext-Manager benötigen. Während des Winters von Xinjiang, China, sollten Sie eine Tür sofort schließen, wenn Sie eine Tür zu öffnen. wenn Sie vergessen, es zu schließen, werden Sie kalt werden.

 class Door:
     def __init__(self):
         self.doorstatus='the door was closed when you are not at home'
         print(self.doorstatus)
     def __enter__(self):
         print('I have opened the door')
         return self
     def __exit__(self,*args):
         print('pong!the door has closed')
     def fetchsomethings(self):
         print('I have fetched somethings')

, wenn die Dinge zu Hause holen, sollten Sie eine Tür öffnen, holen Somethings und in der Nähe der Tür.

 with Door() as dr:
     dr.fetchsomethings()

Die Ausgabe lautet:

the door was closed when you are not at home
I have opened the door
I have fetched somethings
pong!the door has closed

Erklärung

Wenn Sie eine Tür Klasse initiieren, wird es aufrufen __ init __ Methode, druckt „Die Tür geschlossen wurde, wenn Sie nicht im Haus sind“ und __ __ eingeben Methode, druckt „Ich habe die Tür geöffnet haben“ und gibt eine Tür Instanz namens dr. wenn Aufforderung self.fetchsomethings in mit Block wird das Verfahren drucken "Ich habe geholt Somethings" .when der Block finished.the Kontext-Manager aufrufen ist __ __ Ausfahrt Verfahren und es wird Druck „pong! die Tür geschlossen“ .when Sie nicht verwenden Stichwort, __ __ eingeben und __ __ Ausfahrt wird nicht aufgerufen !!!!

with Aussagen oder Kontext-Manager gibt es mit Ressourcen zu unterstützen (obwohl viel mehr verwendet werden kann).

Angenommen, Sie haben eine Datei zum Schreiben geöffnet:

f = open(path, "w")

Sie haben nun eine offene Datei-Handle. Bei der Handhabung von Dateien, kann kein anderes Programm schreiben. Um andere Programme darauf schreiben zu lassen, müssen Sie die Datei-Handle schließen:

f.close()

Aber, vor dem Schließen Ihre Datei ist ein Fehler aufgetreten:

f = open(path, "w")
data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
f.close()

Was passiert, ist jetzt, dass die Funktion oder das ganze Programm verlassen, während die Dateien mit einem offenen Griff zu verlassen. (CPython reinigt Griffe für Abfertigungen und Griffe sind befreit zusammen mit einem Programm, aber Sie sollten rechnen nicht)

A mit Anweisung stellt sicher, dass, sobald Sie es die Vertiefung verlassen, wird es die Datei-Handle schließen:

with open(path, "w") as f:
    data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
    f.write(data)
# In here the file is already closed automatically, no matter what happened.

with Aussagen können für viele Dinge verwendet werden. Zum Beispiel: threading.Lock()

lock = threading.Lock()
with lock:  # Lock is acquired
   do stuff...
# Lock is automatically released.

Fast alles mit einem Kontext-Manager getan mit try: ... finally: ... getan werden, aber Kontext-Manager sind schöner Gebrauch, bequemer, lesbar und durch die Implementierung __enter__ und __exit__ bieten eine einfache Schnittstelle zu verwenden.


Erstellen von Kontext-Manager wird durch die Implementierung getan __enter__() und < a href = "https://docs.python.org/3/reference/datamodel.html#object.__exit__" rel = "noreferrer"> __exit__() in einer normalen Klasse.

__enter__() sagt, was zu tun ist, wenn ein Kontext-Manager startet und __exit__(), wenn ein Kontext-Manager vorhanden ist (die Ausnahme von der __exit__() Methode geben, wenn eine Ausnahme aufgetreten ist)

Eine Verknüpfung für Kontext-Manager erstellen, kann in contextlib . Es umschließt einen Generator als Kontext-Manager.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top