Как создать свое исключение python
Перейти к содержимому

Как создать свое исключение python

  • автор:

Исключения в python. Конструкция try — except для обработки исключений

Python 3 логотип

Исключения (exceptions) — ещё один тип данных в python. Исключения необходимы для того, чтобы сообщать программисту об ошибках.

Самый простейший пример исключения — деление на ноль:

Разберём это сообщение подробнее: интерпретатор нам сообщает о том, что он поймал исключение и напечатал информацию (Traceback (most recent call last)).

Далее имя файла (File «»). Имя пустое, потому что мы находимся в интерактивном режиме, строка в файле (line 1);

Выражение, в котором произошла ошибка (100 / 0).

Название исключения (ZeroDivisionError) и краткое описание исключения (division by zero).

Разумеется, возможны и другие исключения:

В этих двух примерах генерируются исключения TypeError и ValueError соответственно. Подсказки дают нам полную информацию о том, где порождено исключение, и с чем оно связано.

Рассмотрим иерархию встроенных в python исключений, хотя иногда вам могут встретиться и другие, так как программисты могут создавать собственные исключения. Данный список актуален для python 3.3, в более ранних версиях есть незначительные изменения.

  • BaseException — базовое исключение, от которого берут начало все остальные.
    • SystemExit — исключение, порождаемое функцией sys.exit при выходе из программы.
    • KeyboardInterrupt — порождается при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
    • GeneratorExit — порождается при вызове метода close объекта generator.
    • Exception — а вот тут уже заканчиваются полностью системные исключения (которые лучше не трогать) и начинаются обыкновенные, с которыми можно работать.
      • StopIteration — порождается встроенной функцией next, если в итераторе больше нет элементов.
      • ArithmeticError — арифметическая ошибка.
        • FloatingPointError — порождается при неудачном выполнении операции с плавающей запятой. На практике встречается нечасто.
        • OverflowError — возникает, когда результат арифметической операции слишком велик для представления. Не появляется при обычной работе с целыми числами (так как python поддерживает длинные числа), но может возникать в некоторых других случаях.
        • ZeroDivisionError — деление на ноль.
        • IndexError — индекс не входит в диапазон элементов.
        • KeyError — несуществующий ключ (в словаре, множестве или другом объекте).
        • UnboundLocalError — сделана ссылка на локальную переменную в функции, но переменная не определена ранее.
        • BlockingIOError
        • ChildProcessError — неудача при операции с дочерним процессом.
        • ConnectionError — базовый класс для исключений, связанных с подключениями.
          • BrokenPipeError
          • ConnectionAbortedError
          • ConnectionRefusedError
          • ConnectionResetError
          • IndentationError — неправильные отступы.
            • TabError — смешивание в отступах табуляции и пробелов.
            • UnicodeEncodeError — исключение, связанное с кодированием unicode.
            • UnicodeDecodeError — исключение, связанное с декодированием unicode.
            • UnicodeTranslateError — исключение, связанное с переводом unicode.

            Теперь, зная, когда и при каких обстоятельствах могут возникнуть исключения, мы можем их обрабатывать. Для обработки исключений используется конструкция try — except.

            Первый пример применения этой конструкции:

              
            
              
            

            Ещё две инструкции, относящиеся к нашей проблеме, это finally и else. Finally выполняет блок инструкций в любом случае, было ли исключение, или нет (применима, когда нужно непременно что-то сделать, к примеру, закрыть файл). Инструкция else выполняется в том случае, если исключения не было.

            Для вставки кода на Python в комментарий заключайте его в теги

            Как создать свое исключение python

            Иногда возникает необходимость вручную сгенерировать то или иное исключение. Для этого применяется оператор raise . Например, сгенерируем исключение

            try: age = int(input("Введите возраст: ")) if age > 110 or age < 1: raise Exception("Некорректный возраст") print("Ваш возраст:", age) except ValueError: print("Введены некорректные данные") except Exception as e: print(e) print("Завершение программы")

            Оператору raise передается объект BaseException - в данном случае объект Exception. В конструктор этого типа можно ему передать сообщение, которое затем можно вывести пользователю. В итоге, если age будет больше 110 или меньше 1, то сработает оператор raise, который сгенерирует исключение. В итоге управление программой перейдет к блоку except , который обрабатывает исключения типа Exception:

            Введите возраст: 100500 Некорректный возраст Завершение программы

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

            В языке Python мы не ограничены только встроенными типами исключений и можем, применяя наследование, при необходимости создавать свои типы исключений. Например, возьмем следующий класс Person:

            class Person: def __init__(self, name, age): self.__name = name # устанавливаем имя self.__age = age # устанавливаем возраст def display_info(self): print(f"Имя: Возраст: ")

            Здесь класс Person в конструкторе получает значения для имени и возраста и присваивает их приватным переменным name и age. Однако при создании объекта Person мы можем передать в конструктор некорректное с точки зрения логики значение - например, отрицательное число. Одним из способов решения данной ситуации представляет генерация исключения при передаче некорректных значений.

            Итак, определим следующий код программы:

            class PersonAgeException(Exception): def __init__(self, age, minage, maxage): self.age = age self.minage = minage self.maxage = maxage def __str__(self): return f"Недопустимое значение: . " \ f"Возраст должен быть в диапазоне от до " class Person: def __init__(self, name, age): self.__name = name # устанавливаем имя minage, maxage = 1, 110 if minage < age < maxage: # устанавливаем возраст, если передано корректное значение self.__age = age else: # иначе генерируем исключение raise PersonAgeException(age, minage, maxage) def display_info(self): print(f"Имя: Возраст: ") try: tom = Person("Tom", 37) tom.display_info() # Имя: Tom Возраст: 37 bob = Person("Bob", -23) bob.display_info() except PersonAgeException as e: print(e) # Недопустимое значение: -23. Возраст должен быть в диапазоне от 1 до 110

            В начале здесь определен класс PersonAgeException, который наследуется от класса Exception. Как правило, собственные классы исключений наследуются от класса Exception. Класс PersonAgeException предназначен для исключений, связанных с возрастом пользователя.

            В конструкторе PersonAgeException получаем три значения - собственное некорректное значение, которое послужило причиной исключения, а также минимальное и максимальное значения возраста.

            class PersonAgeException(Exception): def __init__(self, age, minage, maxage): self.age = age self.minage = minage self.maxage = maxage def __str__(self): return f"Недопустимое значение: . " \ f"Возраст должен быть в диапазоне от до "

            В функции __str__ определяем текстовое представление класса - по сути сообщение об ошибке.

            В конструкторе класса Persoon проверяем переданное для возраста пользователя значение. И если это значение не соответствует определенному диапазону, то генерируем исключение типа PersonAgeException:

            raise PersonAgeException(age, minage, maxage)

            При применении класса Person нам следует учитывать, что конструктор класса может сгенерировать исключение при передаче некорректного значения. Поэтому создание объектов Person обертывается в конструкцию try..except:

            try: tom = Person("Tom", 37) tom.display_info() # Имя: Tom Возраст: 37 bob = Person("Bob", -23) # генерируется исключение типа PersonAgeException bob.display_info() except PersonAgeException as e: print(e) # Недопустимое значение: -23. Возраст должен быть в диапазоне от 1 до 110

            И если при вызове конструктора Person будет сгенерировано исключение типа PersonAgeException, то управление программой перейдет к блоку except, который обрабатывает исключения типа PersonAgeException в виде вывода информации об исключении на консоль.

            Создание классов исключений

            В Python можно создавать собственные классы исключений. Они должны напрямую или опосредованно быть потомками класса Exception .

            class MyError(Exception): def __init__(self, text): self.txt = text a = input("Input positive integer: ") try: a = int(a) if a < 0: raise MyError("You give negative!") except ValueError: print("Error type of value!") except MyError as mr: print(mr) else: print(a)
            Input positive integer: -10 You give negative!

            В данном случае в выражении MyError("You give negative!") создается экземпляр собственного класса исключений. С помощью raise исключение возбуждается. В перехватившей его соответствующей ветке except исключение присваивается переменной mr .

            У объектов класса Exception (и производных от него) определен метод __str__() так, чтобы выводить значения атрибутов. Поэтому можно не обращаться напрямую к полям объекта, например, так: mr.txt .

            Кроме того у экземпляров Exception есть атрибут args . Через него можно получать доступ к отдельным полям:

            class MyError(Exception): def __init__(self, text, num): self.txt = text self.n = num a = input("Input positive integer: ") try: a = int(a) if a < 0: raise MyError("You give negative!", a) except ValueError: print("Error type of value!") except MyError as mr: print(mr) print(mr.args) print(mr.args[0]) print(mr.args[1]) else: print(a)
            Input positive integer: -3 ('You give negative!', -3) ('You give negative!', -3) You give negative! -3

            Пример наследования от классов-исключений. При перехвате родительский класс "ловит" дочерние, но не наоборот.

            class General(Exception): pass class Specific1(General): pass class Specific2(General): pass def raiser0(): x = General() raise x def raiser1(): x = Specific1() raise x def raiser2(): x = Specific2() raise x for func in (raiser0, raiser1, raiser2): try: func() except General: import sys print(sys.exc_info()[0])

            Исключения — Python: Погружаясь в классы

            Исключения играют важную роль в программировании. Они помогают обрабатывать непредвиденные ошибки и предотвращать критические сбои.

            В этом уроке мы рассмотрим, как работают исключения, как создавать собственные исключения и как их обрабатывать.

            Исключения и перехват исключений

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

            Пример простого исключения:

            try: do_something_dangerous() except Exception as e: print("Something happened", e) 

            В данном примере функция do_something_dangerous() может выбросить исключение. Мы оборачиваем ее вызов в блок try . Если исключение выбрасывается, оно перехватывается блоком except . В итоге мы печатаем сообщение о том, что произошло, вместе с информацией об исключении.

            Но как понять что случилось? Иногда это важно. Разные ошибки могут приводить к разному поведению программы. Кроме того, не все ошибки требуют обработки в текущем месте программы.

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

            Обработка стандартных исключений играет ключевую роль в создании устойчивого кода. Однако иногда возникает потребность создать свои исключения для точного контроля над ошибками в программе.

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

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

            class MyException(Exception): pass 

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

            Теперь посмотрим, как этим можно воспользоваться:

            try: # Какой-то код except MyException as e: # Делаем что-нибудь одно except Exception as e: # Делаем что-нибудь другое 

            Если какой-то код генерирует исключение MyException , мы обрабатываем его особым образом. В противном случае мы обрабатываем остальные исключения блоком except Exception .

            Можно разделять ошибки с помощью разных классов, наследующихся от базового класса Exception :

            class MyError(Exception): pass class FirstError(MyError): pass class SecondError(MyError): pass 

            Рассмотрим, как использовать одновременно все эти классы исключений:

            try: # Код, который может вызвать исключение pass except FirstError: # Обрабатываем FirstError pass except SecondError: # Обрабатываем SecondError pass except MyError: # Обрабатываем MyError pass except Exception as e: # Во всех остальных случаях, например, бросаем исключение снова raise e 

            Обработка любого базового исключения автоматически влечет за собой обработку всех наследников текущего класса. Например, если перехватить MyError , этот блок также будет реагировать на FirstError и SecondError . Чтобы избежать этой проблемы, нужно разместить обработчики для FirstError и SecondError перед обработчиком MyError .

            В самом Python уже есть иерархия исключений , которая позволяет разделять реакцию на разные типы ошибок.

            При создании собственных исключений рекомендуется создавать высокоуровневое исключение, которое наследуется от Exception или BaseException . Далее все специфические исключения вашей программы или библиотеки могут наследоваться от этого высокоуровневого исключения. Это позволяет легко группировать и обрабатывать исключения по их типу. А также позволяет изолировать обработку ошибок конкретной библиотеки буквально одним блоком except .

            Но что делать, когда возникает ситуация, требующая выполнения определенных действий независимо от наличия ошибок в коде? Например, когда необходимо освободить ресурсы или выполнить другие важные операции. Для решения этой проблемы у нас есть конструкция finally , которая обеспечивает гарантированное выполнение кода, независимо от того, возникло исключение или нет.

            Блок finally

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

            В Python для этого есть блок finally , который будет выполнен независимо от того, возникло исключение или нет:

            try: # Какой-то код except MyException as e: # Делаем что-нибудь одно finally: # Вызовется в любом случае 

            Это полезно для освобождения ресурсов или выполнения действий, которые должны произойти независимо от результата выполнения кода.

            Открыть доступ

            Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

            • 130 курсов, 2000+ часов теории
            • 1000 практических заданий в браузере
            • 360 000 студентов

            Наши выпускники работают в компаниях:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *