Über das Fangen einer Ausnahme

696

Wie kann ich einen try/ exceptBlock schreiben , der alle Ausnahmen abfängt?

user469652
quelle
4
In den meisten Fällen machen Sie wahrscheinlich etwas falsch, wenn Sie versuchen, eine Ausnahme zu erkennen. Ich meine, Sie können einfach etwas in Ihrem Code falsch schreiben und Sie werden es sogar nicht wissen. Es ist eine gute Praxis, bestimmte Ausnahmen zu erfassen.
Vwvolodya
12
Genauer gesagt ist das Abfangen aller möglichen Ausnahmen nur dann ein Problem, wenn sie lautlos abgefangen werden. Es ist schwer vorstellbar, wo dieser Ansatz sonst angemessen ist, außer wo die abgefangenen Fehlermeldungen gedruckt sys.stderrund möglicherweise protokolliert werden. Das ist eine absolut gültige und häufige Ausnahme.
Evgeni Sergeev
hast du versucht : try: whatever() except Exception as e: exp_capture() ?
Charlie Parker

Antworten:

564

Sie können, aber Sie sollten wahrscheinlich nicht:

try:
    do_something()
except:
    print "Caught it!"

Dies wird jedoch auch Ausnahmen wie KeyboardInterruptund das wollen Sie normalerweise nicht, oder? Es sei denn, Sie lösen die Ausnahme sofort erneut aus - siehe folgendes Beispiel aus den Dokumenten :

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise
Tim Pietzcker
quelle
30
Mögliche Problemumgehung
Mikel
15
Ihre letzte Aussage ist nicht wahr, Sie müssen explizit sagen, dass except Exception:das Bare, außer Sie haben dort auch die BaseException abfangen.
Pykler
7
Sie sollten wirklich auf stderr drucken.
Nyuszika7h
41
Ich bin sehr, sehr stark mit der Aussage "sollte nicht" nicht einverstanden. Sie sollten es sparsam tun. Es gibt Zeiten, in denen Sie mit Bibliotheken von Drittanbietern zu tun haben (manchmal dynamisch geladen !!), die mit Ausnahmen völlig verrückt geworden sind und deren Aufspüren eine sehr schmerzhafte Aufgabe sein kann. Wenn Sie nur eine verpassen, haben Sie eine sehr sehr großer schmerzhafter Fehler in Ihrem System. Davon abgesehen ist es gut, so viele wie möglich aufzuspüren und angemessen zu behandeln und dann einen Backup-Fang für alle zu haben, die Sie verpassen.
Blaze
26
Was ich auch seltsam finde, ist, dass es in einer Enten-Schreibsprache, in der Sie keine Instanzvariablen deklarieren, plötzlich sehr besorgt ist, nicht alle Ihre Ausnahmen einzugeben. Hmm!
Blaze
834

Abgesehen von einer bloßen except:Klausel (die, wie andere gesagt haben, nicht verwendet werden sollte), können Sie einfach Folgendes erfassen Exception:

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

Normalerweise würden Sie dies immer nur auf der äußersten Ebene Ihres Codes in Betracht ziehen, wenn Sie beispielsweise vor dem Beenden sonst nicht erfasste Ausnahmen behandeln möchten.

Der Vorteil except Exceptiongegenüber dem Nackten exceptbesteht darin, dass es einige Ausnahmen gibt, die es offensichtlich nicht abfängt, KeyboardInterruptund SystemExit: Wenn Sie diese abfangen und verschlucken, können Sie es jedem schwer machen, Ihr Skript zu beenden.

Duncan
quelle
Ich hatte das Gleiche im Kopf, aber es ist ein Nachteil. Nehmen wir an, es gibt zwei Fehler, wenn sie einmal abgefangen werden. Wenn Sie nur drucken, verlassen Sie den Try-Block und kennen den zweiten Fehler nie. .
6
Für alle, die sich fragen, wird dies, ganz im Gegensatz zu meiner Erwartung, immer noch Dinge wie Ints ausschließen, zumindest in Python 2.x.
Joseph Garvin
5
@JosephGarvin, das ist falsch, dh dies fängt keine "Nicht-Ausnahmen" ab, die keine Unterklasse haben Exception. Beachten Sie, dass es unmöglich ist, inteine Ausnahme auszulösen, und wenn Sie dies versuchen, wird eine TypeErrorAusnahme ausgelöst except Exception, die in einem solchen Fall von der beiliegenden Klausel erfasst wird. Auf der anderen Seite kann eine Klasse im alten Stil ausgelöst werden und als "Nicht-Ausnahme" qualifiziert werden, die keine Unterklasse enthält Exception- dies wird durch eine bloße exceptKlausel, aber nicht durch eine except ExceptionKlausel erfasst.
Yoel
4
@ JosephGarvin überprüfen Sie diesen Blogeintrag: chris-lamb.co.uk/posts/no-one-expects-string-literal-exception Ich bin mit @Yoel in diesem Fall, Ihre Tests haben gerade denTypeError
Duncan
2
@CharlieParker nichts Falsches daran, sie zu fangen, wenn Sie das wollen, aber meistens nicht. Ein Anruf sys.exit()bedeutet normalerweise, dass Sie erwarten, dass die App beendet wird, aber wenn Sie SystemExit abfangen, wird dies nicht der Fall sein. Wenn Sie in einem laufenden Skript die Strg-C-Taste drücken (Strg-Pause unter Windows), erwarten Sie ebenfalls, dass das Programm stoppt, den Fehler nicht abfängt und weitermacht. Sie können jedoch eine oder beide davon abfangen, wenn Sie eine Bereinigung durchführen möchten, bevor diese vorhanden ist.
Duncan
100

Sie können dies tun, um allgemeine Ausnahmen zu behandeln

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message
vwvolodya
quelle
8
Dies fängt möglicherweise nicht alle Ausnahmen ab, da die Basisklasse für alle Ausnahmen BaseException ist und ich auf Produktionscode gestoßen bin, der nicht zur Exception-Klassenfamilie gehört. Weitere Informationen hierzu finden Sie unter docs.python.org/3/library/… .
DDay
4
Dies erfasst nicht alle Ausnahmen.
Andy_A̷n̷d̷y̷
6
Technisch sollte es alle nicht systemexistierenden Ausnahmen abfangen. Aus den Dokumenten @DDay verlinkt: " Ausnahme BaseException: Die Basisklasse für alle integrierten Ausnahmen. Sie soll nicht direkt von benutzerdefinierten Klassen geerbt werden (verwenden Sie dazu Exception)." Sofern Sie nicht mit Code arbeiten, der dies ignoriert, oder systembedürftige Ausnahmen abfangen müssen, sollte die Verwendung der oben genannten Regeln in Ordnung sein.
Peter Cassetta
@PeterCassetta Wann möchte man System-Exit-Ausnahmen abfangen? Es scheint der rote Faden in der Frage zu sein, dass wir diese nicht fangen wollen, aber ich verstehe nicht warum. Warum nicht normalerweise?
Charlie Parker
68

Um alle möglichen Ausnahmen zu fangen, fangen Sie BaseException. Es befindet sich oben in der Ausnahmehierarchie:

Python 3: https://docs.python.org/3.5/library/exceptions.html#exception-hierarchy

Python 2.7: https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

Aber wie andere bereits erwähnt haben, benötigen Sie dies normalerweise nicht, nur für bestimmte Fälle.

Gitaarik
quelle
1
Ist es ungewöhnlich, den Fortschritt eines lang laufenden Jobs nach dem Drücken von Strg-C zu speichern?
BallpointBen
54

Sehr einfaches Beispiel, ähnlich dem hier gefundenen:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

Wenn Sie versuchen, ALLE Ausnahmen abzufangen, setzen Sie Ihren gesamten Code in die Anweisung "try:" anstelle von 'print ". Führen Sie eine Aktion aus, die möglicherweise eine Ausnahme auslöst.' '.

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

Im obigen Beispiel wird die Ausgabe in dieser Reihenfolge angezeigt:

1) Ausführen einer Aktion, die eine Ausnahme auslösen kann.

2) Schließlich wird direkt nach dem Ausführen der try-Anweisung aufgerufen, ob eine Ausnahme ausgelöst wird oder nicht.

3) "Eine Ausnahme wurde ausgelöst!" oder "Alles sieht gut aus!" abhängig davon, ob eine Ausnahme ausgelöst wurde.

Hoffe das hilft!

Joshua Burns
quelle
26

Insbesondere mit Python 3.0 und höher gibt es mehrere Möglichkeiten, dies zu tun

Ansatz 1

Dies ist ein einfacher Ansatz, der jedoch nicht empfohlen wird, da Sie nicht genau wissen, in welcher Codezeile die Ausnahme tatsächlich ausgelöst wird:

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

Ansatz 2

Dieser Ansatz wird empfohlen, da er detailliertere Informationen zu jeder Ausnahme enthält. Es enthält:

  • Zeilennummer für Ihren Code
  • Dateiname
  • Der eigentliche Fehler ausführlicher

Der einzige Nachteil ist, dass Tracback importiert werden muss.

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()
grepit
quelle
21

Ich habe gerade diesen kleinen Trick herausgefunden, um zu testen, ob Ausnahmenamen in Python 2.7 vorhanden sind. Manchmal habe ich bestimmte Ausnahmen im Code behandelt, daher brauchte ich einen Test, um festzustellen, ob dieser Name in einer Liste der behandelten Ausnahmen enthalten ist.

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception
Danilo
quelle
2
try:
    whatever()
except:
    # this will catch any exception or error

Es ist erwähnenswert, dass dies keine richtige Python-Codierung ist. Dadurch werden auch viele Fehler abgefangen, die Sie möglicherweise nicht abfangen möchten.

Yuval Adam
quelle
Verwenden Sie einfach, außer dass Sie nicht alle Ausnahmen zwischenspeichern, wie in einigen anderen Antworten erwähnt. Sie müssen BaseException für diesen Zweck verwenden, aber wie Sie sagten, sollte niemand alle Ausnahmen wie diese abfangen. Ich denke, es ist für den Anfang in
Ordnung,