Обработка исключений в Python

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

Что такое исключения?

Исключения — это события, нарушающие нормальный поток выполнения программы, которые могут быть обработаны специальными конструкциями языка.

Зачем нужна обработка исключений?

Обработка исключений позволяет:

  1. Предотвращать аварийное завершение программы — ваша программа продолжит работу, даже если что-то пошло не так
  2. Отделять код обработки ошибок от основной логики — делает код более читаемым и понятным
  3. Централизованно обрабатывать разные типы ошибок — упрощает структуру программы
  4. Делать программу более устойчивой — она сможет корректно работать даже в неожиданных ситуациях

Блоки try-except

Основной механизм обработки исключений в Python — блок try-except. Он позволяет:

  • Изолировать потенциально опасный код
  • Перехватывать ошибки
  • Выполнять альтернативные действия
  • Продолжать выполнение программы

Синтаксис блока try-except

Python 3.13
try:
    # Рискованный код, который может вызвать исключение
except ТипИсключения:
    # Код, который выполнится при возникновении указанного исключения

Вот простой пример:

Python 3.13
>>> try:
...     # Код, который может вызвать исключение
...     result = 10 / 0  # Деление на ноль вызовет ZeroDivisionError
... except ZeroDivisionError:
...     # Код, который выполнится при возникновении исключения
...     print("Ошибка: деление на ноль!")
Ошибка: деление на ноль!

Полная структура блока try-except

Полная структура блока try-except включает дополнительные секции:

Python 3.13
try:
    # Рискованный код
except ТипИсключения1:
    # Обработка исключения типа 1
except ТипИсключения2:
    # Обработка исключения типа 2
else:
    # Выполняется, если в блоке try не возникло исключений
finally:
    # Выполняется всегда, независимо от наличия исключений

Обработка исключений разных типов

Последовательная обработка разных исключений

Можно обрабатывать разные типы исключений по-разному:

Python 3.13
>>> try:
...     # Несколько операций, которые могут вызвать разные исключения
...     file_name = input("Введите имя файла: ")  # Допустим, введено "data.txt"
...     file = open(file_name, "r")
...     line = file.readline()
...     number = int(line.strip())
...     result = 100 / number
...     print(f"Результат: {result}")
... except FileNotFoundError:
...     print(f"Файл {file_name} не найден")
... except ValueError:
...     print("Невозможно преобразовать данные в число")
... except ZeroDivisionError:
...     print("Ошибка: деление на ноль")
... except Exception as e:
...     print(f"Произошла неизвестная ошибка: {e}")
Файл data.txt не найден

Важно: Python проверяет блоки except в порядке их объявления и выполняет первый подходящий блок.

Обработка нескольких исключений одним блоком

Если для разных исключений нужна одинаковая обработка:

Python 3.13
>>> try:
...     value = int("abc")
...     result = 10 / 0
... except (ValueError, ZeroDivisionError):
...     print("Произошла ошибка в вычислениях")
Произошла ошибка в вычислениях

Блоки else и finally

Блок else

Блок else выполняется только если в блоке try не возникло исключений:

Python 3.13
>>> try:
...     number = int("42")  # Это выполнится успешно
... except ValueError:
...     print("Это не число")
... else:
...     # Этот блок выполнится, так как исключения не было
...     print(f"Успешно! Число: {number}")
...     print(f"Квадрат числа: {number ** 2}")
Успешно! Число: 42
Квадрат числа: 1764

Блок else полезен, когда нужно выполнить код только после успешного выполнения рискованной операции.

Блок finally

Блок finally выполняется всегда, независимо от того, произошло исключение или нет:

Python 3.13
>>> try:
...     f = open("example.txt", "w")
...     f.write("Привет, мир!")
...     # Предположим, здесь может произойти исключение
... except IOError:
...     print("Произошла ошибка ввода-вывода")
... finally:
...     print("Закрытие файла")
...     f.close()  # Файл будет закрыт в любом случае
Закрытие файла

Блок finally обычно используется для:

  • Освобождения ресурсов (закрытие файлов, соединений с базой данных)
  • Очистки временных данных
  • Логирования завершения операции

Получение информации об исключении

Используйте as для получения объекта исключения:

Python 3.13
>>> try:
...     result = 10 / 0
... except ZeroDivisionError as e:
...     print(f"Тип исключения: {type(e).__name__}")
...     print(f"Сообщение: {e}")
Тип исключения: ZeroDivisionError
Сообщение: division by zero

Вызов исключений

Вы можете сами вызывать исключения с помощью оператора raise:

Python 3.13
>>> def check_age(age):
...     if age < 0:
...         raise ValueError("Возраст не может быть отрицательным")
...     if age < 18:
...         print("Вы несовершеннолетний")
...     else:
...         print("Вы совершеннолетний")

>>> try:
...     check_age(-5)
... except ValueError as e:
...     print(f"Ошибка: {e}")
Ошибка: Возраст не может быть отрицательным

Создание собственных исключений

Можно создавать собственные классы исключений, наследуя их от стандартных:

Python 3.13
# Создаем собственный класс исключения
>>> class InvalidEmailError(Exception):
...     """Вызывается, когда email не соответствует формату"""
...     pass

>>> def validate_email(email):
...     if "@" not in email:
...         raise InvalidEmailError("Email должен содержать символ @")
...     print(f"Email {email} корректен")

>>> try:
...     validate_email("user.example.com")
... except InvalidEmailError as e:
...     print(f"Ошибка валидации: {e}")
Ошибка валидации: Email должен содержать символ @

Практические рекомендации

1. Определяйте конкретные исключения

Python 3.13
# Плохо:
>>> try:
...     number = int("abc")
... except:  # Перехватывает все исключения
...     print("Ошибка")

# Хорошо:
>>> try:
...     number = int("abc")
... except ValueError:
...     print("Неверный формат числа")
Неверный формат числа

2. Минимизируйте код в блоке try

Python 3.13
# Хорошо:
>>> try:
...     file = open("data.txt", "r")
... except FileNotFoundError:
...     print("Файл не найден")
...     file = None

>>> if file:
...     try:
...         content = file.read()
...     except:
...         print("Ошибка при чтении файла")
...     finally:
...         file.close()
Файл не найден

3. Используйте else и finally правильно

Python 3.13
>>> def get_value_from_list(my_list, index):
...     try:
...         value = my_list[index]
...     except IndexError:
...         print(f"Индекс {index} вне диапазона")
...         return None
...     else:
...         # Этот код выполнится только если исключения не было
...         print(f"Значение успешно получено")
...         return value
...     finally:
...         # Этот код выполнится всегда
...         print("Операция доступа к списку завершена")

>>> result = get_value_from_list([1, 2, 3], 1)
>>> print(f"Результат: {result}")
Значение успешно получено
Операция доступа к списку завершена
Результат: 2
>>> result = get_value_from_list([1, 2, 3], 10) >>> print(f"Результат: {result}")
Индекс 10 вне диапазона
Операция доступа к списку завершена
Результат: None

Проверка понимания

Какой блок выполнится всегда, независимо от того, произошло исключение или нет?

Заключение

Обработка исключений — это ваш надежный защитник от хаоса в коде. Она превращает потенциальные катастрофы в контролируемые ситуации, позволяя вашим программам изящно справляться с неожиданностями. Правильно используя try-except, else и finally, вы создаете более надежный и устойчивый код. 🛡️


Мы с вами на связи
Русский