Python try except: как обрабатывать исключения (else, finally)

Категория: Python · Язык: Python · Обновлено:

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

Базовый пример

Python
def to_int(text):
    try:
        return int(text)
    except ValueError:
        return None

print(to_int("42"))     # 42
print(to_int("абв"))    # None

Несколько типов ошибок

Python
def divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return "деление на ноль"
    except TypeError:
        return "нужны числа"

print(divide(10, 2))      # 5.0
print(divide(1, 0))       # деление на ноль
print(divide("1", 2))     # нужны числа

Одну реакцию на несколько типов задают кортежем: except (ValueError, TypeError):.

else и finally

Python
def read_number(text):
    try:
        number = int(text)
    except ValueError:
        print("не число")
        return None
    else:
        print("успех")        # выполняется только если ошибки не было
        return number
    finally:
        print("готово")       # выполняется всегда, даже после return

result = read_number("7")   # печатает «успех», затем «готово»
print(result)               # 7

При вызове сначала печатается успех, затем готово, и только после этого функция возвращает число. В finally обычно закрывают файлы, соединения и блокировки.

Получить текст ошибки

Python
try:
    {"a": 1}["b"]
except KeyError as error:
    print(f"нет ключа: {error}")   # нет ключа: 'b'

Запись except Exception as e перехватывает почти все ошибки. Используйте её только там, где вы действительно собираетесь что-то сделать с любой ошибкой, например записать в журнал.

Выбросить ошибку самому

Python
def set_age(age):
    if age < 0:
        raise ValueError("возраст не может быть отрицательным")
    return age

try:
    set_age(-5)
except ValueError as error:
    print(error)   # возраст не может быть отрицательным

Своя ошибка и цепочка причин

Python
class ConfigError(Exception):
    """Ошибка настроек приложения."""

def load_port(raw):
    try:
        return int(raw)
    except ValueError as error:
        raise ConfigError(f"некорректный порт: {raw!r}") from error

try:
    load_port("http")
except ConfigError as error:
    print(error)                        # некорректный порт: 'http'
    print(type(error.__cause__).__name__)   # ValueError

Запись raise ... from error сохраняет исходную ошибку в __cause__, поэтому в трассировке видны обе.

Как не надо

Частые вопросы

Чем отличаются else и finally?

else выполняется только если исключения не было. finally выполняется в любом случае: после успеха, после перехваченной ошибки и даже при return.

Как вывести полную трассировку ошибки?

Выполните import traceback и вызовите traceback.print_exc() внутри except. Для записи в журнал используйте logging.exception("сообщение").