Laut Python-Dokumentation zu Idiomen und Anti-Idiomen in Bezug auf Ausnahmen : "Sie sollten Versuchen Sie, so wenig wie möglich außer Klauseln in Ihrem Code zu verwenden - die, die Sie verwenden, sind normalerweise innerhalb von Aufrufen, die immer erfolgreich sein sollten, oder eine Auffangfunktion in einer Hauptfunktion. " Nehmen Sie diesen Satz in Abschnitte ...
"Sie sollten versuchen, so wenige außer-Klauseln in Ihrem Code zu verwenden, wie Sie können"
Ein bisschen verwirrend für einen Neuling wie mich, ich dachte es wäre eine gute Übung in Python den EAFP Stil -ie viele try
und except
Anweisungen. Oder verpasse ich den Punkt?
"die, die du verwendest, sind normalerweise innerhalb von Anrufen, die immer erfolgreich sein sollten"
Ich verstehe den Punkt, der hier gemacht wird, nicht.
"oder ein Catch-All in einer Hauptfunktion."
Also ist es ein guter Stil für irgendeinen Code, der eine Exception auslöst, einfach den Aufruf-Stack hinauf zu geben, bis er die oberste Ebene erreicht, wo Sie wirklich generische Exception-Behandlung haben?
Was den ersten Punkt betrifft, ist der ganze Punkt der Verwendung von Ausnahmen, dass Sie nicht jede Zeile in eine umbrechen müssen! Z.B. In C werden Fehler normalerweise durch den Rückgabewert eines Funktionsaufrufs bestimmt. Sie müssen diese also nach jedem Anruf überprüfen, wenn Sie alle Fehler abfangen wollen. Mit Python können Sie einen (möglicherweise großen) Block von Anweisungen gruppieren, die in einem try / except-Block zusammenlaufen und nur alle Fehler einmal behandeln.
Der zweite Punkt ist, dass Sie (wenn möglich) Fehler in der Nähe des Punktes beheben möchten, an dem sie auftreten. Z.B. Sie lesen Daten aus einem Netzwerk und erhalten null Bytes. In diesem Fall ist es normalerweise vollkommen in Ordnung, zu warten und es erneut zu versuchen.
Der letzte Punkt ist, dass ein Fehler manchmal so groß ist, dass er nicht auf niedriger Ebene behandelt werden kann. Z.B. Wenn Sie versuchen, eine Datei zu öffnen, die nicht existiert, schlägt sie fehl. Und Ihr Programm kann nicht machen, was es mit dem Inhalt der Datei machen würde. Es ist am besten, das auf der obersten Ebene des Programms zu behandeln und den Benutzer nach einem anderen Dateinamen zu fragen oder vielleicht das Programm zu beenden.
"Sie sollten versuchen, so wenige außer-Klauseln in Ihrem Code zu verwenden, wie Sie können"
Es ist einfach, Ihren Code mit Ausnahmen zu verwässern:
%Vor% Hier ist es wahrscheinlich in Ordnung, das ZeroDivisionError
propagieren zu lassen. Sie müssen es nicht fangen.
"die, die du verwendest, sind normalerweise innerhalb von Anrufen, die immer erfolgreich sein sollten"
Schauen Sie sich beispielsweise diesen Code an, der eine Datei liest oder einen zwischengespeicherten Wert zurückgibt. Es ist normalerweise erfolgreich, trotz der Ausnahme KeyError
:
"oder ein Catch-All in einer Hauptfunktion."
Wenn Ihr Programm interaktiv ist, möchten Sie wahrscheinlich fast alles auf oberster Ebene erfassen. Hier ist die oberste Schleife eines interaktiven Befehlszeilenprogramms:
%Vor%Ich denke, der Punkt ist, dass Ausnahmen nur für "außergewöhnliche" Umstände verwendet werden sollten. Das ist die Bedeutung hinter der Verwendung "bei Anrufen, die normalerweise erfolgreich sein werden". Ein Beispiel dafür könnte eine Berechnung sein, die unter einigen wirklich seltsamen Umständen eine Division durch Null beendet. Dann können Sie das in eine try / except-Anweisung einschließen, um mit dieser Möglichkeit umzugehen.
Der Catch-All in einer Hauptfunktion wäre für dasselbe Szenario anwendbar. Nehmen wir an, Ihre Berechnungen enden irgendwo tief im Callstack mit einer Division durch Null. Von diesem Punkt aus können Sie nicht fortfahren. Es hat also keinen Sinn, eine try / except-Anweisung genau zum Zeitpunkt des Fehlers zu haben. Es wäre sinnvoller, nur einen auf einer höheren Ebene zu haben, wo man vernünftigerweise von dem Fehler erholen kann.
Das Beispiel in der Dokumentation ist ein Beispiel dafür. Wenn Sie 'get_status' aufrufen, erwarten Sie, dass die Datei vorhanden ist. Wenn dies nicht der Fall ist, haben Sie die Ausnahmeanweisung, um sich damit zu befassen (obwohl, wie erwähnt, in diesem speziellen Fall die Aussage 'mit' viel besser ist).
Die Python-Philosophie ist typischerweise "um Vergebung bitten, nicht um Erlaubnis". Aber die Idee ist nicht, eine try-except-Klausel zu verwenden, um ALLE möglichen Fehler zu erfassen. Im Idealfall wird jeder try-except nur die relevanten Fehler abfangen.
BAD (gibt keinen bestimmten Ausnahmetyp an):
%Vor%GUT (behandelt nur die Ausnahme, die wir erwarten):
%Vor% Der Grund dafür ist, dass wir andere mögliche Codefehler nicht verdecken. Was wäre, wenn in diesem Beispiel i
1,8 wäre? Das erste Beispiel würde Not Found!
ausgeben und das eigentliche Problem verdecken, aber das zweite Beispiel würde TypeError: list indices must be integers, not float
zurückgeben und uns mitteilen, dass unser Code einen logischen Fehler aufweist.