Mehrere Ausnahmen in einer Zeile abfangen (außer Block)

2756

Ich weiß, dass ich tun kann:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

Ich kann das auch machen:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

Aber wenn ich dasselbe in zwei verschiedenen Ausnahmen tun möchte, ist das Beste, was ich mir jetzt vorstellen kann, Folgendes zu tun:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreBeingMeanException:
    # say please

Gibt es eine Möglichkeit, wie ich so etwas tun kann (da in beiden Ausnahmen folgende Maßnahmen ergriffen werden müssen say please):

try:
    # do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
    # say please

Das wird jetzt wirklich nicht funktionieren, da es der Syntax für:

try:
    # do something that may fail
except Exception, e:
    # say please

Meine Bemühungen, die beiden unterschiedlichen Ausnahmen zu erfassen, kommen also nicht genau zum Tragen.

Gibt es eine Möglichkeit, dies zu tun?

inspectorG4dget
quelle
6
Beachten Sie, dass letztere in Python 3 keine gültige Syntax mehr ist.
Gerrit

Antworten:

3724

Aus der Python-Dokumentation :

Eine Ausnahmeklausel kann beispielsweise mehrere Ausnahmen als Tupel in Klammern benennen

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Oder nur für Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

Das Trennen der Ausnahme von der Variablen durch ein Komma funktioniert in Python 2.6 und 2.7 weiterhin, ist jedoch veraltet und funktioniert in Python 3 nicht. jetzt solltest du verwenden as.

mechanisches Fleisch
quelle
9
Ich habe es versucht ... mit einem list, und es ergab sich ein TypeError. Sieht so aus, als müssten die Fehler in einem sein, tupledamit das Fangen wie erwartet funktioniert.
BallpointBen
4
Warum hätten Sie jemals eine Liste verwendet, wenn Sie deutlich sehen, dass dokumentiert ist, dass in diesem Fall ein Tupel benötigt wird?
mechanisches
6
Es war unklar, ob das "Tupel in Klammern" lediglich syntaktisch war oder ob ein echtes Tupel erforderlich war. "In Klammern" ist irreführend, da Sie möglicherweise ein Tupel ohne Klammern an anderer Stelle erstellen und es dann in der exceptZeile verwenden. Es wird nur notwendigerweise in Klammern gesetzt, wenn es in der exceptZeile erstellt wird.
BallpointBen
5
@ JosephBani, was ist mit Generatorausdrücken?
jammertheprogrammer
12
@ JosephBani Das stimmt überhaupt nicht. In 2 + (x * 2), (x * 2)ist sicherlich kein Tupel. Klammern sind ein allgemeines Gruppierungskonstrukt. Das definierende Merkmal eines Tupels ist, dass es ein Komma enthält - siehe Python-Dokumentation : "Beachten Sie, dass es tatsächlich das Komma ist, das ein Tupel bildet, nicht die Klammern."
Soren Bjornstad
314

Wie fange ich mehrere Ausnahmen in einer Zeile (außer Block)?

Mach das:

try:
    may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
    handle(error) # might log or have some other default behavior...

Die Klammern sind aufgrund der älteren Syntax erforderlich, bei der das Fehlerobjekt mithilfe von Kommas einem Namen zugewiesen wurde. Das asSchlüsselwort wird für die Zuweisung verwendet. Sie können einen beliebigen Namen für das Fehlerobjekt verwenden, ich errorpersönlich bevorzuge .

Beste Übung

Um dies auf eine Weise zu tun, die derzeit und vorwärts mit Python kompatibel ist, müssen Sie die Ausnahmen durch Kommas trennen und in Klammern setzen, um sich von der früheren Syntax zu unterscheiden, bei der die Ausnahmeinstanz einem Variablennamen zugewiesen wurde, indem Sie dem Ausnahmetyp folgen, der mit a abgefangen werden soll Komma.

Hier ist ein Beispiel für eine einfache Verwendung:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.exit(0)

Ich gebe nur diese Ausnahmen an, um zu vermeiden, dass Fehler ausgeblendet werden. Wenn ich auf sie stoße, erwarte ich die vollständige Stapelverfolgung.

Dies ist hier dokumentiert: https://docs.python.org/tutorial/errors.html

Sie können die Ausnahme einer Variablen zuweisen ( eist üblich, bevorzugen jedoch möglicherweise eine ausführlichere Variable, wenn Sie eine lange Ausnahmebehandlung haben oder Ihre IDE nur größere Auswahlen hervorhebt, wie meine.) Die Instanz verfügt über ein args-Attribut. Hier ist ein Beispiel:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError) as err: 
    print(err)
    print(err.args)
    sys.exit(0)

Beachten Sie, dass in Python 3 das errObjekt außerhalb des Gültigkeitsbereichs liegt, wenn der exceptBlock geschlossen wird.

Veraltet

Möglicherweise wird Code angezeigt, der den Fehler mit einem Komma belegt. Diese Verwendung, das einzige in Python 2.5 und früheren Versionen verfügbare Formular, ist veraltet. Wenn Sie möchten, dass Ihr Code in Python 3 vorwärtskompatibel ist, sollten Sie die Syntax aktualisieren, um das neue Formular zu verwenden:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    sys.exit(0)

Wenn Sie die Zuweisung von Komma-Namen in Ihrer Codebasis sehen und Python 2.5 oder höher verwenden, wechseln Sie zu der neuen Methode, damit Ihr Code beim Upgrade kompatibel bleibt.

Der suppressKontextmanager

Die akzeptierte Antwort besteht aus mindestens 4 Codezeilen:

try:
    do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Die try, except, passLinien können in einer einzigen Zeile mit dem gehandhabt werden 3,4 Unterdrückungs - Kontext - Manager, in Python :

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

Wenn Sie also passbestimmte Ausnahmen haben möchten , verwenden Sie suppress.

Aaron Hall
quelle
2
Gute Ergänzung suppress, viel besser lesbar als nur passamexcept
Mache
50

Aus der Python-Dokumentation -> 8.3 Ausnahmen behandeln :

Eine tryAnweisung kann mehr als eine Ausnahmeklausel enthalten, um Handler für verschiedene Ausnahmen anzugeben. Es wird höchstens ein Handler ausgeführt. Handler behandeln nur Ausnahmen, die in der entsprechenden try-Klausel auftreten, nicht in anderen Handlern derselben try-Anweisung. Eine Ausnahmeklausel kann mehrere Ausnahmen als Tupel in Klammern benennen, zum Beispiel:

except (RuntimeError, TypeError, NameError):
    pass

Beachten Sie, dass die Klammern um dieses Tupel erforderlich sind, da außer ValueError, e:der Syntax, die für das verwendet wird, was normalerweise wie except ValueError as e:in modernem Python geschrieben wird (siehe unten). Die alte Syntax wird aus Gründen der Abwärtskompatibilität weiterhin unterstützt. Dieses Mittel except RuntimeError, TypeErrorist nicht gleich , except (RuntimeError, TypeError):sondern zu except RuntimeError as TypeError:denen ist nicht das, was Sie wollen.

fedorqui 'SO hör auf zu schaden'
quelle
35

Wenn Sie häufig eine große Anzahl von Ausnahmen verwenden, können Sie ein Tupel vordefinieren, sodass Sie es nicht viele Male neu eingeben müssen.

#This example code is a technique I use in a library that connects with websites to gather data

ConnectErrs  = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)

def connect(url, data):
    #do connection and return some data
    return(received_data)

def some_function(var_a, var_b, ...):
    try: o = connect(url, data)
    except ConnectErrs as e:
        #do the recovery stuff
    blah #do normal stuff you would do if no exception occurred

ANMERKUNGEN:

  1. Wenn Sie auch andere Ausnahmen als die im vordefinierten Tupel abfangen müssen, müssen Sie einen anderen Ausnahmeblock definieren.

  2. Wenn Sie eine globale Variable einfach nicht tolerieren können, definieren Sie sie in main () und geben Sie sie bei Bedarf weiter ...

weißer Bart
quelle
17

Eine Möglichkeit, dies zu tun, ist ..

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

und eine andere Möglichkeit besteht darin, eine Methode zu erstellen, die die von einem exceptBlock ausgeführte Aufgabe ausführt und sie über den gesamten exceptBlock aufruft, den Sie schreiben.

try:
   You do your operations here;
   ......................
except Exception1:
    functionname(parameterList)
except Exception2:
    functionname(parameterList)
except Exception3:
    functionname(parameterList)
else:
   If there is no exception then execute this block. 

def functionname( parameters ):
   //your task..
   return [expression]

Ich weiß, dass der zweite nicht der beste Weg ist, dies zu tun, aber ich zeige nur eine Reihe von Möglichkeiten, dies zu tun.

M.Usman
quelle
Ich verwende die zweite, weil ich zwei verschiedene Ausnahmen habe, die jeweils unterschiedlich verarbeitet werden müssen. Stimmt etwas nicht, wenn man es so macht?
Majikman
@majikman Die zweite Methode mit mehreren Klauseln, die jeweils dieselbe Funktion aufrufen, ist nicht die beste, wenn Sie versuchen, sich nicht zu wiederholen und mit zwei Ausnahmen dasselbe zu tun. (Siehe die anderen Antworten für den richtigen Weg, dies zu tun). Es exceptist jedoch normal , mehrere Klauseln zu haben, wenn Sie die Ausnahmen unterschiedlich behandeln möchten.
Gleichnamiger