Zu meiner Schande kann ich nicht herausfinden, wie ich mit Ausnahmen für die Python-Anweisung 'with' umgehen soll. Wenn ich einen Code habe:
with open("a.txt") as f:
print f.readlines()
Ich möchte wirklich mit 'Datei nicht gefundene Ausnahme' umgehen, um etwas zu tun. Aber ich kann nicht schreiben
with open("a.txt") as f:
print f.readlines()
except:
print 'oops'
und kann nicht schreiben
with open("a.txt") as f:
print f.readlines()
else:
print 'oops'
Das Einfügen von 'with' in eine try / exception-Anweisung funktioniert nicht. Andernfalls wird keine Ausnahme ausgelöst. Was kann ich tun, um Fehler innerhalb der 'with'-Anweisung auf pythonische Weise zu verarbeiten?
python
exception-handling
grigoryvp
quelle
quelle
with
Aussage bricht eine umgebendetry...except
Aussage nicht auf magische Weise .Antworten:
Wenn Sie eine andere Behandlung von Fehlern aus dem offenen Aufruf als dem Arbeitscode wünschen, können Sie Folgendes tun:
quelle
try...except
Blöcke hinzufügenwith
, um näher an der Quelle einer Ausnahme zu sein, die nichts damit zu tun hatopen()
.Der beste "pythonische" Weg, dies unter Ausnutzung der
with
Anweisung zu tun , ist als Beispiel Nr. 6 in PEP 343 aufgeführt , das den Hintergrund der Anweisung angibt .Wird wie folgt verwendet:
quelle
try...except
Anweisung.Die with-Anweisung ist seit Python 2.6 ohne
__future__
Import verfügbar . Sie können es bereits in Python 2.5 herunterladen (aber jetzt ist es Zeit für ein Upgrade!) Mit:Hier ist das Nächste, was Sie korrigieren müssen. Sie sind fast da, haben aber
with
keineexcept
Klausel:__exit__
Wenn die Methode eines Kontextmanagers zurückgegeben wird,False
wird der Fehler nach Abschluss erneut angezeigt. Wenn es zurückkehrtTrue
, wird es unterdrückt. Dasopen
eingebaute Gerät__exit__
kehrt nicht zurückTrue
, Sie müssen es also nur in einem Versuch verschachteln, außer Block:Und Standard-Boilerplate: Verwenden Sie kein nacktes,
except:
das fängtBaseException
und jede andere mögliche Ausnahme und Warnung. Seien Sie mindestens so genau wieException
und für diesen Fehler vielleicht fangenIOError
. Fangen Sie nur Fehler ab, auf die Sie vorbereitet sind.In diesem Fall würden Sie also Folgendes tun:
quelle
Unterscheidung zwischen den möglichen Ursprüngen von Ausnahmen, die aus einer zusammengesetzten
with
Aussage hervorgehenDie Unterscheidung zwischen Ausnahmen, die in einer
with
Anweisung auftreten, ist schwierig, da sie an verschiedenen Stellen auftreten können. Ausnahmen können von einer der folgenden Stellen (oder darin genannten Funktionen) ausgelöst werden:ContextManager.__init__
ContextManager.__enter__
with
ContextManager.__exit__
Weitere Informationen finden Sie in der Dokumentation zu Context Manager-Typen .
Wenn wir zwischen diesen verschiedenen Fällen unterscheiden wollen, reicht es nicht aus , nur das
with
in ein zu wickelntry .. except
. Betrachten Sie das folgende Beispiel (amValueError
Beispiel, aber es könnte natürlich durch einen anderen Ausnahmetyp ersetzt werden):Hier
except
fängt der Wille Ausnahmen ab, die von allen vier verschiedenen Orten ausgehen, und erlaubt daher keine Unterscheidung zwischen ihnen. Wenn wir die Instanziierung des Kontextmanagerobjekts außerhalb von verschiebenwith
, können wir unterscheiden zwischen__init__
undBLOCK / __enter__ / __exit__
:Tatsächlich hat dies nur beim
__init__
Teil geholfen, aber wir können eine zusätzliche Sentinel-Variable hinzufügen, um zu überprüfen, ob der Hauptteil derwith
Ausführung ausgeführt wurde (dh zwischen__enter__
und den anderen zu unterscheiden):Der schwierige Teil besteht darin, zwischen Ausnahmen zu unterscheiden, die von
BLOCK
und__exit__
weil eine Ausnahme, die dem Hauptteil deswith
Testaments entgeht, übergeben wird, an__exit__
die entschieden werden kann, wie damit umgegangen werden soll (siehe die Dokumente ). Wenn sich jedoch etwas__exit__
auslöst, wird die ursprüngliche Ausnahme durch die neue ersetzt. Um diese Fälle zu behandeln, können wir eine allgemeineexcept
Klausel in den Hauptteil der hinzufügenwith
, um mögliche Ausnahmen zu speichern, die sonst unbemerkt geblieben wären, und sie mit derexcept
später im äußersten gefangenen zu vergleichen - wenn sie gleich sind, bedeutet dies, dass der Ursprung warBLOCK
oder anders war es__exit__
(falls__exit__
die Ausnahme unterdrückt wird, indem ein wahrer Wert als äußerster zurückgegeben wirdexcept
wird einfach nicht ausgeführt).Alternativer Ansatz unter Verwendung der in PEP 343 genannten äquivalenten Form
PEP 343 - Die "with" -Anweisung gibt eine äquivalente "non-with" -Version der
with
Anweisung an. Hier können wir die verschiedenen Teile leicht umwickelntry ... except
und so zwischen den verschiedenen möglichen Fehlerquellen unterscheiden:Normalerweise reicht ein einfacherer Ansatz aus
Die Notwendigkeit einer solchen speziellen Ausnahmebehandlung sollte ziemlich selten sein, und normalerweise ist es ausreichend, das Ganze
with
in einentry ... except
Block zu wickeln . Insbesondere wenn die verschiedenen Fehlerquellen durch unterschiedliche (benutzerdefinierte) Ausnahmetypen angezeigt werden (die Kontextmanager müssen entsprechend gestaltet sein), können wir leicht zwischen ihnen unterscheiden. Zum Beispiel:quelle