Unterschied zwischen Ausnahme: und Ausnahme Ausnahme als e: in Python

140

Die beiden folgenden Codeausschnitte machen dasselbe. Sie fangen jede Ausnahme ab und führen den Code im except:Block aus

Snippet 1 -

try:
    #some code that may throw an exception
except:
    #exception handling code

Snippet 2 -

try:
    #some code that may throw an exception
except Exception as e:
    #exception handling code

Was genau ist der Unterschied zwischen beiden Konstrukten?

narendranathjoshi
quelle
7
@ user2725093 das ist nicht die gleiche frage. Derjenige, mit dem Sie verlinkt haben, fragt, was der Unterschied zwischen except Exception, e:und ist except Exception as e:. Diese Frage fragt, was der Unterschied zwischen except:und ist except Exception as e:.
Dennis

Antworten:

153

Im zweiten können Sie auf die Attribute des Ausnahmeobjekts zugreifen:

>>> def catch():
...     try:
...         asd()
...     except Exception as e:
...         print e.message, e.args
... 
>>> catch()
global name 'asd' is not defined ("global name 'asd' is not defined",)

Aber es nicht fangen BaseExceptionoder die System Austritt Ausnahmen SystemExit, KeyboardInterruptund GeneratorExit:

>>> def catch():
...     try:
...         raise BaseException()
...     except Exception as e:
...         print e.message, e.args
... 
>>> catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch
BaseException

Was eine bloße Ausnahme macht:

>>> def catch():
...     try:
...         raise BaseException()
...     except:
...         pass
... 
>>> catch()
>>> 

Siehe die eingebauten Ausnahmen Abschnitt der Dokumentation und der Fehler und Ausnahmen Abschnitt des Tutorials für weitere Informationen.

agf
quelle
21
Hier gibt es keine Magie. Exceptionwird abgeleitet von BaseException, deshalb except Exceptionfängt nicht BaseException. Wenn Sie schreiben except BaseException, wird es auch gefangen. Bare exceptfängt einfach alles.
Fjarri
2
Ich sollte darauf hinweisen, dass ein Bare exceptdas letzte in einer Reihe von exceptBlöcken sein muss, während Sie keinen Fehler erhalten, wenn Sie es except Exceptionvor andere exceptBlöcke stellen: Sie werden nur stillschweigend ignoriert (wenn sie ExceptionUnterklassen behandeln). Etwas, auf das man achten muss.
Vanessa Phipps
@MatthewPhipps Das ist der springende Punkt, nicht wahr? Wie bei case-Anweisungen oder if-else-Blöcken springt die Ausführung zur ersten Bedingung, die übereinstimmt ...
Basic
1
@Basic Nur auf einen weiteren Unterschied zwischen nackt exceptund except Exception. "Etwas, auf das man achten muss" sieht jetzt etwas seltsam aus, aber zu der Zeit erwartete ich, dass Python den spezifischsten exceptBlock auswählen würde , unabhängig davon, wo er sich befand, und war ein wenig enttäuscht, etwas anderes herauszufinden.
Vanessa Phipps
Es ist auch erwähnenswert, dass das zweite Formular nur verwendet werden sollte, wenn Sie sich nicht darum kümmern, was die Ausnahme war, oder wenn Sie es auf sinnvolle Weise behandeln möchten.
Josh J
51
except:

akzeptiert alle Ausnahmen, während

except Exception as e:

nur akzeptiert Ausnahmen , dass Sie gemeint zu fangen.

Hier ist ein Beispiel für eines, das Sie nicht fangen sollen:

>>> try:
...     input()
... except:
...     pass
... 
>>> try:
...     input()
... except Exception as e:
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

Der erste brachte das zum Schweigen KeyboardInterrupt!

Hier ist eine kurze Liste:

issubclass(BaseException, BaseException)
#>>> True
issubclass(BaseException, Exception)
#>>> False


issubclass(KeyboardInterrupt, BaseException)
#>>> True
issubclass(KeyboardInterrupt, Exception)
#>>> False


issubclass(SystemExit, BaseException)
#>>> True
issubclass(SystemExit, Exception)
#>>> False

Wenn Sie eines davon fangen möchten, ist es am besten, dies zu tun

except BaseException:

um darauf hinzuweisen, dass Sie wissen, was Sie tun.


Alle Ausnahmen stammen von BaseExceptionund diejenigen, die Sie täglich fangen sollen (diejenigen, die für den Programmierer geworfen werden ), erben auch von Exception.

Veedrac
quelle
except(Exception)fängt nie KeyboardInterruptFehler. as ehat nichts damit zu tun.
Pandita
2
Ich habe nie gesagt, dass es so ist. Ich habe das nicht einmal erwähnt as e, weil ich angenommen habe, dass es offensichtlich ist, was es tut.
Veedrac
2
Gibt es einen Fall, in dem eine Person BaseException abfängt UND weiß, was sie tut?
Davos
2
@Davos Ja, vielleicht bevorzugen Sie es, wenn Sie eine vorübergehende Protokollierung durchführen oder wenn Sie dem Benutzer eine Konsole anbieten, von der Sie keine Ausnahmen möchten SystemExitoder denen Sie KeyboardInterruptentkommen möchten . Kein häufiger Fall, aber es kommt vor.
Veedrac
14

Mit einigen Ausnahmen gibt es Unterschiede, z. B. KeyboardInterrupt.

Lesen von PEP8 :

Eine bloße Ausnahme: -Klausel fängt SystemExit- und KeyboardInterrupt-Ausnahmen ab, was es schwieriger macht, ein Programm mit Control-C zu unterbrechen, und kann andere Probleme verschleiern. Wenn Sie alle Ausnahmen abfangen möchten, die Programmfehler signalisieren, verwenden Sie außer Ausnahme: (nackte Ausnahme entspricht Ausnahme BaseException :).

Diego Herranz
quelle
3

Wenn Sie das zweite Formular verwenden, erhalten Sie im Blockbereich eine Variable ( asin Ihrem Beispiel basierend auf der Klausel benannt e), an die exceptdas Ausnahmeobjekt gebunden ist, sodass Sie die Informationen in der Ausnahme (Typ, Nachricht, Stapelverfolgung usw.) verwenden können Behandeln Sie die Ausnahme in einem speziell zugeschnittenen Herrenhaus.

Silas Ray
quelle
1

Eine andere Sichtweise. Überprüfen Sie die Details der Ausnahme:

In [49]: try: 
    ...:     open('file.DNE.txt') 
    ...: except Exception as  e: 
    ...:     print(dir(e)) 
    ...:                                                                                                                                    
['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', 'args', 'characters_written', 'errno', 'filename', 'filename2', 'strerror', 'with_traceback']

Es gibt viele "Dinge", auf die mit der Syntax 'as e' zugegriffen werden kann.

Dieser Code sollte ausschließlich die Details dieser Instanz anzeigen.

Jouell
quelle