Kodokon kodokon.com

Ошибки и исключения: try, except, raise

Перехватывай предсказуемые сбои через try/except/else/finally и возбуждай собственные исключения, чтобы сигнализировать о некорректных данных.

9 мин · 3 вопросов

Открыть этот урок в Kodokon

Настоящая программа падает: файла нет, ввод некорректен, сеть оборвалась. Python сигнализирует о таких ситуациях исключениями: они прерывают выполнение и поднимаются вверх по стеку вызовов, пока их не перехватит try/except. Профессиональный рефлекс: перехватывать максимально конкретное исключение и как можно ближе к тому месту, где ты знаешь, что с ним делать.

PYTHON
def parse_age(text):
    try:
        return int(text)
    except ValueError:
        return None

print(parse_age("34"))      # 34
print(parse_age("thirty"))  # None
Мы перехватываем именно ValueError, а не любые ошибки.

Полный блок состоит из четырёх ветвей. try содержит рискованный код, except обрабатывает сбой, else выполняется только если исключения не было, а finally выполняется в любом случае - идеально, чтобы освободить ресурс или записать лог. Смысл else: держать try минимальным, чтобы с первого взгляда было видно, какая строка может упасть.

PYTHON
values = ["10", "abc", "25"]
total = 0

for value in values:
    try:
        number = int(value)
    except ValueError:
        print(f"Skip : {value}")
    else:
        total += number
    finally:
        print(f"Process : {value}")

print(total)  # 35
else выполняется только при отсутствии ошибки; finally выполняется всегда.

Твои функции тоже могут возбуждать собственные исключения через raise, как только полученные данные оказываются некорректными: лучше упасть сразу с понятным сообщением, чем выдать неверный результат. Определи отдельный класс, наследующий от Exception: вызывающий код сможет перехватить именно его, не задевая случайно другие ошибки.

PYTHON
class EmptyCartError(Exception):
    pass

def checkout(items):
    if not items:
        raise EmptyCartError("Empty cart.")
    return round(sum(items), 2)

try:
    print(checkout([]))
except EmptyCartError as error:
    print(f"Error : {error}")
Отдельное бизнес-исключение делает сбой явным и точечным.

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Когда выполняется блок else в try/except?
    • Только если в try не было возбуждено исключение
    • Только если исключение было перехвачено
    • В любом случае, после try
  2. В каких случаях выполняется блок finally?
    • Только если было возбуждено исключение
    • Только если исключения не было
    • В любом случае, с исключением или без
  3. Почему стоит избегать голого except:, который ловит всё?
    • Он прячет настоящие баги и сильно усложняет отладку
    • Он медленнее точечного except
    • Он работает только с исключениями стандартной библиотеки