wake-up-neo.com

Wie kann man in diesem Fall eine "zu breite Ausnahme" verhindern?

Ich habe eine Liste von Funktionen erhalten, die möglicherweise fehlschlagen, und wenn eine fehlschlägt, möchte ich nicht, dass das Skript stoppt, sondern mit der nächsten Funktion fortfährt.

Ich führe es mit so etwas aus:

list_of_functions = [f_a,f_b,f_c]
for current_function in list_of_functions:
    try:
        current_function()
    except Exception:
        print(traceback.format_exc())

Es funktioniert gut, ist aber nicht PEP8-konform:

Wenn Sie Ausnahmen abfangen, geben Sie bestimmte Ausnahmen an, wenn möglich statt eine bloße Ausnahme zu verwenden: Klausel.

Verwenden Sie zum Beispiel:

try:
    import platform_specific_module
except ImportError:
    platform_specific_module = None

Eine bloße Ausnahme: Klausel fängt SystemExit und KeyboardInterrupt Ausnahmen, die es schwieriger machen, ein Programm mit Control-C zu unterbrechen, und kann andere Probleme tarnen. Wenn Sie alle Ausnahmen abfangen möchten Verwenden Sie für das Signal Programmfehler, außer Ausnahme: (Bare außer ist äquivalent zu Ausnahme BaseException:).

Eine gute Faustregel besteht darin, die Verwendung bloßer "Ausnahmen" -Klauseln auf zwei .__ zu beschränken. Fälle:

Wenn der Ausnahmebehandler das Traceback ausgibt oder protokolliert; Dem Benutzer ist zumindest bekannt, dass ein Fehler aufgetreten ist.

Wenn der Code einige Bereinigungsarbeiten ausführen muss, lässt sich die Ausnahme dann mit Raise nach oben ausbreiten. versuchen ... endlich kann ein besserer .__ sein. Weg, um diesen Fall zu behandeln.

Wie geht das der gute Weg?

15
Blusky

Der PEP8-Leitfaden, den Sie zitieren, legt nahe, dass Sie in Ihrem Fall eine bloße Ausnahme verwenden dürfen, sofern Sie die Fehler protokollieren. Ich würde denken, dass Sie so viele Ausnahmen abdecken sollten, wie Sie damit umgehen können/können, und dann den Rest und pass protokollieren, z.

import logging

list_of_functions = [f_a,f_b,f_c]
for current_function in list_of_functions:
    try:
        current_function()
    except KnownException:
        raise
    except Exception as e:
        logging.exception(e)
21
Ed Smith

//youtrack.jetbrains.com/issue/PY-9715

PY-9715 Inkonsistente Prüfung "Zu breite Ausnahmebestimmungen" [Überprüfung zu breiter Ausnahmebestimmungen] [1]

//legacy.python.org/dev/peps/pep-0348/

BaseException

Die Oberklasse, von der alle Ausnahmen erben müssen. Ihr Name war ausgewählt, um anzuzeigen, dass es sich an der Basis der Ausnahmehierarchie befindet. selbst eine Ausnahme. "Erhebbar" wurde als Name angesehen. es wurde weitergegeben, weil sein Name die Tatsache nicht richtig widerspiegelte dass es selbst eine Ausnahme ist.

Direkte Vererbung von BaseException wird nicht erwartet und lautet für den allgemeinen Fall entmutigt. Die meisten benutzerdefinierten Ausnahmen sollten Erben Sie stattdessen von Exception. Dies ermöglicht das Abfangen von Exceptions auf Arbeiten Sie im allgemeinen Fall weiter, um alle Ausnahmen zu erfassen, die sollte gefangen werden. Direkte Vererbung von BaseException sollte nur .__ sein. in Fällen, in denen eine völlig neue Kategorie von Ausnahmen gewünscht wird.

Aber für Fälle, in denen alle Ausnahmen blind gefangen werden sollten, mit Ausnahme von BaseException wird funktionieren.

[1] http://i.stack.imgur.com/8UByz.png

//youtrack.jetbrains.com/issue/PY-9715

//legacy.python.org/dev/peps/pep-0348/

0
xgqfrms

Ich denke, in einigen seltenen Fällen ist es gerechtfertigt, allgemeine Ausnahmen zu erwischen, und es gibt eine Möglichkeit, die PEP8-Inspektion auszutricksen:

list_of_functions = [f_a,f_b,f_c]
for current_function in list_of_functions:
try:
    current_function()
except (ValueError, Exception):
    print(traceback.format_exc())

Sie können ValueError durch jedes andere ersetzen. Es funktioniert bei mir (zumindest in PyCharm).

0

Meinen Sie vielleicht, dass jede Funktion unterschiedliche Ausnahmen haben kann? Wenn Sie den Ausnahmetyp in der Ausnahmeklausel benennen, kann es sich um einen beliebigen Namen handeln, der auf eine Ausnahme verweist, nicht nur auf den Klassennamen.

z.B.

def raise_value_error():
    raise ValueError

def raise_type_error():
    raise TypeError

def raise_index_error():
    doesnt_exist

func_and_exceptions = [(raise_value_error, ValueError), (raise_type_error, TypeError), 
    (raise_index_error, IndexError)]

for function, possible_exception in func_and_exceptions:
   try:
       function()
   except possible_exception as e:
       print("caught", repr(e), "when calling", function.__name__)

druckt:

caught ValueError() when calling raise_value_error
caught TypeError() when calling raise_type_error
Traceback (most recent call last):
  File "run.py", line 14, in <module>
    function()
  File "run.py", line 8, in raise_index_error
    doesnt_exist
NameError: name 'doesnt_exist' is not defined

Natürlich wissen Sie nicht, was zu tun ist, wenn eine Ausnahme auftritt. Aber da Sie es einfach ignorieren und weitermachen wollen, ist das kein Problem.

0
Dunes