Złap wiele wyjątków w jednym wierszu (oprócz bloku)

2754

Wiem, że mogę:

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

Mogę też to zrobić:

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

Ale jeśli chcę zrobić to samo w ramach dwóch różnych wyjątków, najlepsze, co mogę teraz wymyślić, to zrobić:

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

Czy jest jakiś sposób, aby zrobić coś takiego (ponieważ działanie w obu wyjątkach to say please):

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

Teraz to naprawdę nie zadziała, ponieważ pasuje do składni:

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

Tak więc mój wysiłek, aby uchwycić dwa wyjątki, nie do końca się udaje.

Czy jest na to sposób?

inspectorG4dget
źródło
6
Zauważ, że w Pythonie 3 ta ostatnia nie jest już poprawną składnią.
gerrit

Odpowiedzi:

3722

Z dokumentacji Python :

Klauzula wyjątku może na przykład nazywać wiele wyjątków jako krotkę w nawiasach okrągłych

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Lub tylko dla Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

Oddzielenie wyjątku od zmiennej przecinkiem będzie nadal działać w Pythonie 2.6 i 2.7, ale teraz jest przestarzałe i nie działa w Pythonie 3; teraz powinieneś używać as.

mięso_mechaniczne
źródło
9
Spróbowałem ... z list, i to spowodowało TypeError. Wygląda na to, że błędy muszą występować w tuplecelu poprawnego działania zgodnie z oczekiwaniami.
BallpointBen
4
Dlaczego miałbyś kiedykolwiek korzystać z listy, gdy widzisz wyraźnie, że jest udokumentowane, że w tym przypadku potrzebna jest krotka?
Mechanical_meat
6
Nie było jasne, czy „nawiasowa krotka” jest jedynie składniowa, czy też wymagana jest bona fide krotka. „Nawias” jest mylący, ponieważ możesz utworzyć krotkę bez nawiasów w innym miejscu, a następnie użyć jej w exceptwierszu. Jest koniecznie nawiasowany tylko, jeśli zostanie utworzony w exceptlinii.
BallpointBen
5
@JosephBani, co z wyrażeniami generatora?
jammertheprogrammer
12
@JosephBani To wcale nie prawda. W 2 + (x * 2), (x * 2)z pewnością nie jest krotka. Nawiasy są ogólną konstrukcją grupującą. Cechą charakterystyczną krotki jest to, że zawiera przecinek - patrz dokumentacja Pythona : „Zauważ, że to przecinek tworzy krotkę, a nie nawiasy”.
Soren Bjornstad,
314

Jak wychwycić wiele wyjątków w jednym wierszu (oprócz bloku)

Zrób to:

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

Nawiasy są wymagane ze względu na starszą składnię, która używała przecinków do przypisywania obiektu błędu do nazwy. Słowo askluczowe służy do przypisania. Możesz użyć dowolnej nazwy dla obiektu błędu, wolę errorosobiście.

Najlepsze praktyki

Aby to zrobić w sposób obecnie zgodny i zgodny z Pythonem, musisz oddzielić wyjątki przecinkami i owinąć je nawiasami, aby odróżnić je od wcześniejszej składni, która przypisała wystąpienie wyjątku do nazwy zmiennej, postępując zgodnie z typem wyjątku, który ma zostać przechwycony za pomocą przecinek.

Oto przykład prostego użycia:

import sys

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

Podaję tylko te wyjątki, aby uniknąć ukrywania błędów, które, jeśli napotkam, oczekują śladu pełnego stosu.

Jest to udokumentowane tutaj: https://docs.python.org/tutorial/errors.html

Możesz przypisać wyjątek do zmiennej ( ejest powszechny, ale możesz preferować bardziej szczegółową zmienną, jeśli masz długą obsługę wyjątków lub twoje IDE podświetla tylko wybory większe niż to, co moje). Instancja ma atrybut args. Oto przykład:

import sys

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

Zauważ, że w Pythonie 3 errobiekt nie wchodzi w zakres po zakończeniu exceptbloku.

Przestarzałe

Możesz zobaczyć kod, który przypisuje błąd przecinkiem. To użycie, jedyna forma dostępna w Pythonie 2.5 i wcześniejszych, jest przestarzała, a jeśli chcesz, aby Twój kod był zgodny w przód w Pythonie 3, powinieneś zaktualizować składnię, aby używać nowej formy:

import sys

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

Jeśli widzisz przypisanie nazwy przecinka w swojej bazie kodu i używasz języka Python 2.5 lub nowszego, przełącz się na nowy sposób, aby kod był zgodny podczas aktualizacji.

suppressKierownik kontekst

Akceptowana odpowiedź to tak naprawdę 4 linie kodu, minimum:

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

try, except, passLinie mogą być obsługiwane w jednej linii z menedżerem kontekstowego zatajania dostępnych w Pythonie 3.4 :

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

Więc jeśli chcesz, z passpewnymi wyjątkami, użyj suppress.

Aaron Hall
źródło
2
Dobry dodatek suppress, dużo bardziej czytelny niż po prostu robi passnaexcept
mache
50

Z dokumentacji Pythona -> 8.3 Obsługa wyjątków :

tryStwierdzenie może mieć więcej niż jednym wyjątkiem klauzuli, aby określić teleskopowe dla różnych wyjątków. Zostanie wykonany najwyżej jeden moduł obsługi. Programy obsługi obsługują tylko wyjątki występujące w odpowiedniej klauzuli try, a nie inne programy obsługi tej samej instrukcji try. Klauzula wyjątkowa może nazwać wiele wyjątków jako krotkę w nawiasach, na przykład:

except (RuntimeError, TypeError, NameError):
    pass

Zauważ, że nawiasy wokół tej krotki są wymagane, ponieważ oprócz ValueError, e:tej składni użyto tego, co zwykle jest napisane jak except ValueError as e:w nowoczesnym Pythonie (opisanym poniżej). Stara składnia jest nadal obsługiwana w celu zapewnienia zgodności z poprzednimi wersjami. Oznacza to, że except RuntimeError, TypeErrornie jest równoważne, except (RuntimeError, TypeError):ale do except RuntimeError as TypeError:którego nie jest to, czego chcesz.

fedorqui „SO przestań szkodzić”
źródło
35

Jeśli często używasz dużej liczby wyjątków, możesz wstępnie zdefiniować krotkę, aby nie trzeba było jej wielokrotnie wpisywać.

#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

UWAGI:

  1. Jeśli musisz także złapać inne wyjątki niż te w predefiniowanym krotce, musisz zdefiniować inny wyjątek oprócz bloku.

  2. Jeśli po prostu nie tolerujesz zmiennej globalnej, zdefiniuj ją w main () i przekaż ją w razie potrzeby ...

Biała broda
źródło
17

Jednym ze sposobów na to jest ..

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. 

a innym sposobem jest stworzenie metody wykonującej zadanie wykonywane przez exceptblok i wywołanie go przez cały exceptblok, który piszesz ..

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]

Wiem, że drugi nie jest najlepszym sposobem na zrobienie tego, ale pokazuję tylko kilka sposobów na zrobienie tego.

M.Usman
źródło
Używam drugiego, ponieważ mam dwa różne wyjątki, z których każdy musi być przetwarzany inaczej. Czy jest coś złego w robieniu tego w ten sposób?
majikman
@majikman Druga metoda z wieloma klauzulami, z których każda wywołuje tę samą funkcję, nie jest najlepsza, gdy próbujesz się nie powtarzać i robisz to samo z dwoma wyjątkami. (Zobacz inne odpowiedzi, aby dowiedzieć się, jak to zrobić). Posiadanie wielu exceptklauzul jest jednak normalne, gdy chcesz inaczej obsługiwać wyjątki.
Tytułowy