Python try except: как обрабатывать исключения (else, finally)
Конструкция try / except перехватывает ошибки, чтобы программа не падала. Код, который может сломаться, помещают в try, а реакцию на конкретную ошибку в except ТипОшибки. Блок else выполняется без ошибок, а finally выполняется всегда.
Базовый пример
def to_int(text):
try:
return int(text)
except ValueError:
return None
print(to_int("42")) # 42
print(to_int("абв")) # NoneНесколько типов ошибок
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
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 обычно закрывают файлы, соединения и блокировки.
Получить текст ошибки
try:
{"a": 1}["b"]
except KeyError as error:
print(f"нет ключа: {error}") # нет ключа: 'b'Запись except Exception as e перехватывает почти все ошибки. Используйте её только там, где вы действительно собираетесь что-то сделать с любой ошибкой, например записать в журнал.
Выбросить ошибку самому
def set_age(age):
if age < 0:
raise ValueError("возраст не может быть отрицательным")
return age
try:
set_age(-5)
except ValueError as error:
print(error) # возраст не может быть отрицательнымСвоя ошибка и цепочка причин
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("сообщение").