Разница между исключением: и исключением исключения как e: в Python

140

Оба следующих фрагмента кода делают одно и то же. Они ловят каждое исключение и выполняют код в except:блоке

Фрагмент 1 -

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

Фрагмент 2 -

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

В чем разница в обеих конструкциях?

narendranathjoshi
источник
7
@ user2725093 это не тот же вопрос. Тот, с кем вы связаны, спрашивает, в чем разница между except Exception, e:и except Exception as e:. Этот вопрос спрашивает, в чем разница между except:и except Exception as e:.
Деннис

Ответы:

155

Во втором вы можете получить доступ к атрибутам объекта исключения:

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

Но это не ловит BaseExceptionили системные исключения SystemExit, KeyboardInterruptи 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

Который голый кроме делает:

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

См. Раздел « Встроенные исключения » документации и раздел « Ошибки и исключения » данного руководства для получения дополнительной информации.

AGF
источник
22
Ну, здесь нет магии. Exceptionпроисходит от BaseException, поэтому except Exceptionне ловит BaseException. Если ты напишешь except BaseException, его тоже поймают. Голый exceptпросто ловит все.
Фьярри
2
Я должен отметить, что голое exceptдолжно быть последним в серии exceptблоков, в то время как вы не получите ошибку, если поместите except Exceptionперед другими exceptблоками: они будут просто игнорироваться (если они обрабатывают Exceptionподклассы). Что-то, на что нужно обратить внимание.
Ванесса Фиппс
@ MatthewPhipps В этом все дело, не так ли? подобно операторам case или блокам if-else, выполнение переходит к первому соответствующему условию ...
Basic
1
@Basic Просто указывает на еще одну разницу между голым exceptи except Exception. «Что-то, на что нужно обратить внимание» теперь выглядит немного странно, но в то время я ожидал, что Python выберет самый специфический exceptблок, независимо от того, где он был, и был немного разочарован, узнав иначе.
Ванесса Фиппс
Стоит также отметить, что вторую форму следует использовать только в том случае, если вас не волнует, что это за исключение, или вы хотите обработать его осмысленно.
Джош Дж
51
except:

принимает все исключения, тогда как

except Exception as e:

принимает только те исключения, которые вы должны поймать.

Вот пример того, что вы не должны ловить:

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

Первый заставил замолчать KeyboardInterrupt!

Вот краткий список:

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


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


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

Если вы хотите поймать любой из них, лучше сделать

except BaseException:

указать, что вы знаете, что делаете.


Все исключения проистекают из BaseExceptionтех, которые вы должны поймать изо дня в день (те, которые будут выброшены для программиста) Exception.

Veedrac
источник
except(Exception)никогда не ловит KeyboardInterruptошибки. as eне имеет к этому никакого отношения.
Пандита
2
Я никогда не говорил, что это так. Я ни разу не упомянул as e, потому что предположил, что это очевидно.
Veedrac
2
Есть ли случай, когда человек поймает BaseException и узнает, что он делает?
Давос,
2
@Davos Да, вы можете предпочесть это, когда ведете временную регистрацию, или если вы предлагаете консоль пользователю, для которого вы не хотите, чтобы исключения, такие как SystemExitили KeyboardInterruptот которых скрывались. Не частый случай, но это случается.
Veedrac
14

Существуют различия с некоторыми исключениями, например, KeyboardInterrupt.

Чтение PEP8 :

Простое предложение исключением: будет перехватывать исключения SystemExit и KeyboardInterrupt, затрудняя прерывание программы с помощью Control-C, и может скрывать другие проблемы. Если вы хотите перехватить все исключения, которые сигнализируют об ошибках программы, используйте кроме Exception: (bare кроме эквивалентно исключению BaseException :).

Диего Херранц
источник
3

Использование второй формы дает вам переменную (названную в соответствии с asпредложением в вашем примере e) в области exceptблока с привязанным к ней объектом исключения, так что вы можете использовать информацию в исключении (тип, сообщение, трассировка стека и т. Д.) Для обработать исключение в более специально подобранной усадьбе.

Сайлас Рэй
источник
1

Еще один способ взглянуть на это. Проверьте детали исключения:

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

Есть много «вещей» для доступа с использованием синтаксиса «как e».

Этот код был предназначен исключительно для показа деталей этого экземпляра.

jouell
источник