Обработка исключений в Python
Программа спрашивает у пользователя возраст и прибавляет год:
Python 3.13age = int(input("Сколько вам лет? ")) print("Через год будет", age + 1)
Пока вводят число, всё работает. Но стоит пользователю набрать «сорок» вместо 40, и int() не сможет превратить это в число: программа аварийно завершится с ошибкой ValueError, а строка с print уже не выполнится. Один неверный ввод роняет всю программу.
Обработка исключений нужна как раз для таких моментов: перехватить ошибку, среагировать на неё и продолжить работу, вместо того чтобы падать при первой же неожиданности.
Что такое исключения?
Исключение — это ошибка, возникшая во время выполнения программы. По умолчанию оно прерывает работу, но его можно перехватить и обработать.
Блоки try-except
Основной механизм обработки исключений в Python — блок try-except. Он позволяет:
- Изолировать потенциально опасный код
- Перехватывать ошибки
- Выполнять альтернативные действия
- Продолжать выполнение программы
Синтаксис блока try-except
Python 3.13try: # Рискованный код, который может вызвать исключение except ТипИсключения: # Код, который выполнится при возникновении указанного исключения
Вот простой пример:
Python 3.13try: # Код, который может вызвать исключение result = 10 / 0 # Деление на ноль вызовет ZeroDivisionError except ZeroDivisionError: # Код, который выполнится при возникновении исключения print("Ошибка: деление на ноль!")Ошибка: деление на ноль!
Полная структура блока try-except
Полная структура блока try-except включает дополнительные секции:
Python 3.13try: # Рискованный код except ТипИсключения1: # Обработка исключения типа 1 except ТипИсключения2: # Обработка исключения типа 2 else: # Выполняется, если в блоке try не возникло исключений finally: # Выполняется всегда, независимо от наличия исключений
Обработка исключений разных типов
Последовательная обработка разных исключений
Можно обрабатывать разные типы исключений по-разному:
Python 3.13try: # Несколько операций, которые могут вызвать разные исключения 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.13try: value = int("abc") result = 10 / 0 except (ValueError, ZeroDivisionError): print("Произошла ошибка в вычислениях")Произошла ошибка в вычислениях
Блоки else и finally
Блок else
Блок else выполняется только если в блоке try не возникло исключений:
Python 3.13try: number = int("42") # Это выполнится успешно except ValueError: print("Это не число") else: # Этот блок выполнится, так как исключения не было print(f"Успешно! Число: {number}") print(f"Квадрат числа: {number ** 2}")Успешно! Число: 42 Квадрат числа: 1764
Блок else полезен, когда нужно выполнить код только после успешного выполнения рискованной операции.
Блок finally
Блок finally выполняется всегда, независимо от того, произошло исключение или нет:
Python 3.13try: f = open("example.txt", "w") f.write("Привет, мир!") # Предположим, здесь может произойти исключение except IOError: print("Произошла ошибка ввода-вывода") finally: print("Закрытие файла") f.close() # Файл будет закрыт в любом случаеЗакрытие файла
Блок finally обычно используется для:
- Освобождения ресурсов (закрытие файлов, соединений с базой данных)
- Очистки временных данных
- Логирования завершения операции
Получение информации об исключении
Используйте as для получения объекта исключения:
Python 3.13try: result = 10 / 0 except ZeroDivisionError as e: print(f"Тип исключения: {type(e).__name__}") print(f"Сообщение: {e}")Тип исключения: ZeroDivisionError Сообщение: division by zero
Вызов исключений
Вы можете сами вызывать исключения с помощью оператора raise:
Python 3.13def 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.13def 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}")Значение успешно получено Операция доступа к списку завершена Результат: 2result = get_value_from_list([1, 2, 3], 10) print(f"Результат: {result}")Индекс 10 вне диапазона Операция доступа к списку завершена Результат: None
Проверка понимания
Какой блок выполнится всегда, независимо от того, произошло исключение или нет?
