Różnica między wyjątkiem: i wyjątkiem Wyjątek jako e: w Pythonie

140

Oba poniższe fragmenty kodu robią to samo. Wychwytują każdy wyjątek i wykonują kod w except:bloku

Fragment 1 -

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

Fragment 2 -

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

Jaka jest dokładnie różnica w obu konstrukcjach?

narendranathjoshi
źródło
7
@ user2725093 to nie to samo pytanie. Ten, z którym łączysz się, pyta, jaka jest różnica między except Exception, e:i except Exception as e:. To pytanie dotyczy różnicy między except:i except Exception as e:.
Dennis

Odpowiedzi:

155

W drugim możesz uzyskać dostęp do atrybutów obiektu wyjątku:

>>> 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",)

Ale to nie złapać BaseExceptionlub wyjątki przez system zamykania SystemExit, KeyboardInterrupti 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

Który nagi z wyjątkiem robi:

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

Aby uzyskać więcej informacji, zobacz sekcję Wbudowane wyjątki w dokumentacji oraz sekcję Błędy i wyjątki w samouczku.

agf
źródło
22
Cóż, tutaj nie ma magii. Exceptionpochodzi z BaseException, dlatego except Exceptionnie łapie BaseException. Jeśli napiszesz except BaseException, też zostaniesz złapany. Bare exceptpo prostu łapie wszystko.
fjarri
2
Powinienem zwrócić uwagę, że gołe exceptmusi być ostatnie w serii exceptbloków, podczas gdy nie otrzymasz błędu, jeśli umieścisz je except Exceptionprzed innymi exceptblokami: po prostu zostaną zignorowane po cichu (jeśli obsługują Exceptionpodklasy). Coś, na co trzeba uważać.
Vanessa Phipps
@MatthewPhipps W pewnym sensie o to chodzi, prawda? podobnie jak instrukcje case lub bloki if-else, wykonanie przeskakuje do pierwszego warunku, który pasuje ...
Basic
1
@Basic Po prostu wskazuję inną różnicę między gołymi excepti except Exception. „Coś, na co trzeba uważać” wygląda teraz trochę dziwnie, ale wtedy spodziewałem się, że Python wybierze najbardziej specyficzny exceptblok, niezależnie od tego, gdzie się znajduje, i byłem trochę rozczarowany, gdy dowiedziałem się, że jest inaczej.
Vanessa Phipps,
Warto również zauważyć, że drugi formularz powinien być używany tylko wtedy, gdy nie dbasz o to, jaki był wyjątek lub chcesz obsłużyć go w znaczący sposób.
Josh J
51
except:

akceptuje wszystkie wyjątki, podczas gdy

except Exception as e:

akceptuje tylko wyjątki, że jesteś oznaczało do połowu.

Oto przykład takiego, którego nie powinieneś złapać:

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

Pierwszy uciszył KeyboardInterrupt!

Oto krótka lista:

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


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


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

Jeśli chcesz złapać którykolwiek z nich, najlepiej to zrobić

except BaseException:

wskazać, że wiesz, co robisz.


Wszystkie wyjątki pochodzą od BaseException, a te, które masz codziennie łapać (te, które zostaną wyrzucone dla programisty) również dziedziczą Exception.

Veedrac
źródło
except(Exception)nigdy nie wyłapuje KeyboardInterruptbłędów. as enie ma z tym nic wspólnego.
pandita,
2
Nigdy nie powiedziałem, że tak. Ani razu o tym nie wspomniałem as e, bo zakładałem, że to oczywiste.
Veedrac,
2
Czy istnieje przypadek, w którym osoba złapałaby BaseException I wie, co robi?
Davos,
2
@Davos Tak, możesz to preferować podczas rejestrowania przejściowego lub jeśli oferujesz użytkownikowi konsolę, której nie chcesz, aby wyjątki takie jak SystemExitlub KeyboardInterruptod których uciekały. Nie jest to częsty przypadek, ale zdarza się.
Veedrac
14

Istnieją różnice z pewnymi wyjątkami, np. KeyboardInterrupt.

Czytanie PEP8 :

Sama klauzula except: przechwytuje wyjątki SystemExit i KeyboardInterrupt, utrudniając przerwanie programu za pomocą Control-C i może maskować inne problemy. Jeśli chcesz wyłapać wszystkie wyjątki, które sygnalizują błędy programu, użyj wyjątku Exception: (bare except jest równoważne z wyjątkiem BaseException :).

Diego Herranz
źródło
3

Użycie drugiego formularza daje zmienną (nazwaną na podstawie asklauzuli, w twoim przykładzie e) w zakresie exceptblokowym z powiązanym z nią obiektem wyjątku, dzięki czemu możesz użyć informacji w wyjątku (typ, wiadomość, ślad stosu itp.) zajmij się wyjątkiem w bardziej specjalnie dostosowanym dworze.

Silas Ray
źródło
1

Inny sposób spojrzenia na to. Sprawdź szczegóły wyjątku:

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']

Istnieje wiele „rzeczy”, do których można uzyskać dostęp za pomocą składni „as e”.

Ten kod miał na celu wyłącznie pokazanie szczegółów tej instancji.

jouell
źródło