В чем причина того, что существует только попытка?
try
Блок позволяет обрабатывать ожидаемую ошибку. except
Блок должен поймать только исключения вы готовы к обработке. Если вы обрабатываете неожиданную ошибку, ваш код может сделать что-то не так и скрыть ошибки.
Предложение else
будет выполнено, если ошибок не было, и, не выполняя этот код в try
блоке, вы избежите неожиданной ошибки. Опять же, обнаружение неожиданной ошибки может скрыть ошибки.
пример
Например:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
else:
return something
Пакет «try, кроме» содержит два необязательных предложения else
и finally
. Так оно и есть на самом деле try-except-else-finally
.
else
будет оценивать, только если нет исключения из try
блока. Это позволяет нам упростить более сложный код ниже:
no_error = None
try:
try_this(whatever)
no_error = True
except SomeException as the_exception:
handle(the_exception)
if no_error:
return something
поэтому, если мы сравним a else
с альтернативой (которая может привести к ошибкам), мы увидим, что это сокращает количество строк кода, и мы можем получить более читабельную, поддерживаемую и менее ошибочную кодовую базу.
finally
finally
будет выполняться независимо от того, что, даже если другая строка оценивается с оператором возврата.
Разбит с помощью псевдокода
Это может помочь разобрать это в наименьшей возможной форме, которая демонстрирует все функции, с комментариями. Предположим, что этот синтаксически правильный (но не запускаемый, если не определены имена) псевдокод находится в функции.
Например:
try:
try_this(whatever)
except SomeException as the_exception:
handle_SomeException(the_exception)
# Handle a instance of SomeException or a subclass of it.
except Exception as the_exception:
generic_handle(the_exception)
# Handle any other exception that inherits from Exception
# - doesn't include GeneratorExit, KeyboardInterrupt, SystemExit
# Avoid bare `except:`
else: # there was no exception whatsoever
return something()
# if no exception, the "something()" gets evaluated,
# but the return will not be executed due to the return in the
# finally block below.
finally:
# this block will execute no matter what, even if no exception,
# after "something" is eval'd but before that value is returned
# but even if there is an exception.
# a return here will hijack the return functionality. e.g.:
return True # hijacks the return in the else clause above
Это правда, что мы могли бы вместо этого включить код в else
блок в try
блоке, где он будет работать, если бы не было исключений, но что, если сам этот код вызывает исключение того типа, который мы ловим? Оставив его в try
блоке, можно было бы скрыть эту ошибку.
Мы хотим минимизировать строки кода в try
блоке, чтобы избежать перехвата исключений, которые мы не ожидали, по принципу, что если наш код дает сбой, мы хотим, чтобы он громко провалился. Это лучшая практика .
Насколько я понимаю, исключения не являются ошибками
В Python большинство исключений - ошибки.
Мы можем просмотреть иерархию исключений с помощью pydoc. Например, в Python 2:
$ python -m pydoc exceptions
или Python 3:
$ python -m pydoc builtins
Даст нам иерархию. Мы можем видеть, что большинство видов Exception
ошибок, хотя Python использует некоторые из них для таких вещей, как конечные for
циклы ( StopIteration
). Это иерархия Python 3:
BaseException
Exception
ArithmeticError
FloatingPointError
OverflowError
ZeroDivisionError
AssertionError
AttributeError
BufferError
EOFError
ImportError
ModuleNotFoundError
LookupError
IndexError
KeyError
MemoryError
NameError
UnboundLocalError
OSError
BlockingIOError
ChildProcessError
ConnectionError
BrokenPipeError
ConnectionAbortedError
ConnectionRefusedError
ConnectionResetError
FileExistsError
FileNotFoundError
InterruptedError
IsADirectoryError
NotADirectoryError
PermissionError
ProcessLookupError
TimeoutError
ReferenceError
RuntimeError
NotImplementedError
RecursionError
StopAsyncIteration
StopIteration
SyntaxError
IndentationError
TabError
SystemError
TypeError
ValueError
UnicodeError
UnicodeDecodeError
UnicodeEncodeError
UnicodeTranslateError
Warning
BytesWarning
DeprecationWarning
FutureWarning
ImportWarning
PendingDeprecationWarning
ResourceWarning
RuntimeWarning
SyntaxWarning
UnicodeWarning
UserWarning
GeneratorExit
KeyboardInterrupt
SystemExit
Комментатор спросил:
Допустим, у вас есть метод, который отправляет эхо-запрос на внешний API, и вы хотите обработать исключение в классе вне оболочки API. Вы просто возвращаете e из метода в предложении исключением, где e является объектом исключения?
Нет, вы не raise
вернете исключение, просто создайте его заново, чтобы сохранить трассировку стека.
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
raise
Или в Python 3 вы можете вызвать новое исключение и сохранить обратный след с цепочкой исключений:
try:
try_this(whatever)
except SomeException as the_exception:
handle(the_exception)
raise DifferentException from the_exception
Я уточню в своем ответе здесь .