2013-04-20 17 views
16

Jak radzić sobie z wyjątkiem wszystkich wyjątków?Obsługa wszystkich wyjątków oprócz jednego

try: 
    something 
except NoChildException: 
    raise NoChildException 
except: 
    pass 
+4

Prosta odpowiedź: Nie rób tego. Naprawdę złym pomysłem jest wychwycić wszystkie wyjątki, ponieważ będziesz starał się złapać te, których nie chcesz, ukrywając błędy. Istnieje tylko niewielka liczba uzasadnionych przypadków takiego postępowania. –

+2

Wygląda na to, że odpowiedziałeś na własne pytanie. Powiedz nam, dlaczego nie jesteś zadowolony z tego, co masz. –

+0

@ Robᵩ Nie do końca, jego przykład spowoduje * nowy * wyjątek, a nie ponowne podniesienie starego. –

Odpowiedz

24

Odpowiedź jest po prostu zrobić raise:

try: 
    ... 
except SomeException: 
    raise 
except: 
    ... 

raise bez wyrazu po to będzie proste podbicie ostatni wyrzucony wyjątek (nawet jeśli to było obsługiwane!). To z grubsza odpowiada:

except SomeException as e: 
    raise e 

Jeśli uważasz, że inny wyjątek może być rzucony w bloku catch (oczywiście niemożliwe w tym przypadku), należy użyć tego ostatniego formatu, aby upewnić się ponownie podnieść prawą wyjątek.

Jednakże, jak wskazano w moim komentarzu:

Prosta odpowiedź: Nie. Naprawdę złym pomysłem jest złapanie wszystkich wyjątków od , ponieważ będziesz starał się złapać te, których nie chciałeś, ukrywając błędy. Istnieje tylko niewielka liczba uzasadnionych przypadków, które powodują takie rzeczy.

Po prostu złap błędy, które Twoim zdaniem mogą zostać wyrzucone przez kod i umiesz sobie z nimi poradzić. Jeśli coś jeszcze się stanie, Twój program zakończy działanie - co jest , co chcesz, ponieważ możesz wtedy zobaczyć, dlaczego tak się stało i poprawnie go obsłużyć.

+2

+1 za "nie rób tego" – Aya

+0

zgadzam się. ale mam to: Niepowodzenie: Twoja metoda Patient.update przechwyciła wyjątek typu ZeroDivisionError, gdy nie powinien. Nigdy nie powinieneś używać pustych klauzul 'except 'w swoim kodzie. Tylko wychwytywane NoChildExceptions. zamiast tego: powodzeniem ignorowane podniesiony wyjątek typu: ZeroDivisionError powodzeniem ignorowane podniesiony wyjątek typu: NameError powodzeniem ignorowane podniesiony wyjątek typu: AttributeError powodzeniem ignorowane podniesiony wyjątek typu: Błąd typu powodzeniem ignorowane podniesiony wyjątek typu : ValueError Pomyślnie został podniesiony NoChildException Test zakończony –

+0

@ IvanVulović Więc to czego chcesz to * only * catch 'NoChildException's (co jest dokładnym przeciwieństwem tego, o co prosiłeś), więc po prostu spróbuj: ... except NoChildException: ... ", nie ma potrzeby niczego nadzwyczajnego. –

2

Zaproponuję to jako ulepszenie zaakceptowanej odpowiedzi.

try: 
    dosomestuff() 
except MySpecialException: 
    ttype, value, traceback = sys.exc_info() 
    raise ttype, value, traceback 
except Exception as e: 
    mse = convert_to_myspecialexception_with_local_context(e, context) 
    raise mse 

Takie podejście poprawia zaakceptowanej odpowiedzi utrzymując oryginalną StackTrace gdy MySpecialException zostanie złapany, więc gdy obsługi wyjątku najwyższego poziomu rejestruje wyjątek dostaniesz traceback, który wskazuje, gdzie oryginalny wyjątek .

0

Znalazłem kontekst, w którym łapanie wszystkich błędów, ale jeden nie jest zły, a mianowicie testowanie jednostkowe.

Jeśli mam metody:

def my_method(): 
    try: 
     something() 
    except IOError, e: 
     handle_it() 

może to przekonująco mieć badanej jednostki, która wygląda tak:

def test_my_method(): 
    try: 
     my_module.my_method() 
    except IOError, e: 
     print "shouldn't see this error message" 
     assert False 
    except Exception, e: 
     print "some other error message" 
     assert False 
    assert True 

Bo teraz Wykryto, że my_method prostu wyrzucił nieoczekiwany wyjątek.