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

Как вызвать исключение 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. Конструкция 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 в комментарий заключайте его в теги

            Инструкция raise, принудительно поднимает исключение

            Инструкция raise позволяет программисту принудительно вызвать указанное исключение. Например:

            >>> raise NameError('HiThere') # Traceback (most recent call last): # File "", line 1, in # NameError: HiThere 

            В общем случае инструкция raise повторно вызывает последнее исключение, которое было активным в текущей области видимости. Если нужно определить, было ли вызвано исключение, но не обрабатывать его, более простая форма инструкции raise позволяет повторно вызвать исключение:

            try: raise NameError('HiThere') except NameError: print('Исключение пролетело незаметно!') # Еще какие-то действия, например запись в журнал логов . # затем повторно вызываем `NameError` raise # Исключение пролетело незаметно! # Traceback (most recent call last): # File "", line 2, in # NameError: HiThere 

            Если в текущей области видимости нет активного исключения, то в месте, где указана инструкция raise , без указания , возникает исключение RuntimeError , указывающее на ошибку.

            >>> raise # Traceback (most recent call last): # File "", line 1, in # RuntimeError: No active exception to reraise 

            В противном случае raise вычисляет первое выражение как объект исключения. Он должен быть подклассом BaseException , например Exception или один из его подклассов. Если передается класс исключения, он будет неявно создан путем вызова его конструктора без аргументов.

            # сокращение для 'raise ValueError()' >>> raise ValueError # Traceback (most recent call last): # File "", line 1, in # ValueError 

            При возникновении исключения объект traceback обычно создается автоматически и присоединяется к нему в качестве атрибута __traceback__ . Следовательно можно создать исключение путем raise и установить в него свой собственный traceback за один шаг, используя метод BaseException.with_traceback() , например:

            try: . except SomeException: # Получаем трассировку tb = sys.exception().__traceback__ # передаем трассировку raise AnyException(. ).with_traceback(tb) 

            Инструкция raise и цепочка исключений.

            Если внутри раздела except (конструкции try/except ) появляется НЕперехваченное исключение (например с помощью raise ), то к нему будет привязано исключение, которое было перехвачено инструкцией except в качестве атрибута __cause__ , и оба будут выведены в сообщении об ошибке:

            try: open("database.sqlite") except OSError: raise RuntimeError("не удается обработать ошибку") # Traceback (most recent call last): # File "", line 2, in # FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite' # During handling of the above exception, another exception occurred: # Traceback (most recent call last): # File "", line 4, in # RuntimeError: не удается обработать ошибку 

            Подобный механизм работает неявно, если исключение вызывается внутри обработчика исключений (внутри предложения try ) или внутри предложения finally , то предыдущее исключение присоединяется в качестве атрибута __context__ нового исключения:

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

            def func(): raise ConnectionError try: func() except ConnectionError as exc: raise RuntimeError('Не удалось открыть базу данных') from exc # Traceback (most recent call last): # File "", line 2, in # File "", line 2, in func # ConnectionError # The above exception was the direct cause of the following exception: # Traceback (most recent call last): # File "", line 4, in # RuntimeError: Не удалось открыть базу данных 

            Цепочка исключений может быть явно подавлена/отключена путем ​​указания значения None в предложении from :

            try: a = 1 / 0 except Exception as exc: raise RuntimeError("Случилось что-то плохое") from None # Traceback (most recent call last): # File "", line 4, in # RuntimeError: Случилось что-то плохое 

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

            # например, поступили данные с клавиатуры s = 'apple' try: # пытаемся преобразовать данные num = int(s) except ValueError: raise ValueError("Строка не может быть преобразована в целое число") from None # Traceback (most recent call last): # File "", line 5, in # ValueError: Строка не может быть преобразована в целое число 
            • ОБЗОРНАЯ СТРАНИЦА РАЗДЕЛА
            • Обработка/перехват исключений try/except
            • Инструкция finally, очистка внешних ресурсов
            • Тонкости работы конструкции try/except/else/finally
            • Создание пользовательского класса исключения
            • Обработка группы исключений, оператор except*
            • Эффективная обработка исключений
            • Инструкция raise, принудительный вызов исключений
            • Отладочные утверждение assert
            • Улучшения сообщений об ошибках 3.10
            • Улучшения сообщений об ошибках 3.11
            • Улучшения сообщений об ошибках 3.12

            Мир Python: исключения — Python для продвинутых

            В этом уроке вы узнаете о важном средстве языка, без которого крупная программа не может обойтись. Речь пойдет об исключениях. Что это такое, как ими пользоваться и как создавать собственные?

            Исключительные ситуации или исключения (exceptions) – это ошибки, обнаруженные при исполнении. Например, к чему приведет попытка чтения несуществующего файла? Или если файл был случайно удален пока программа работала? Такие ситуации обрабатываются при помощи исключений.

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

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

            >>> 100 / 0 Traceback (most recent call last): File "", line 1, in 100 / 0 ZeroDivisionError: division by zero 

            В данном случае интерпретатор сообщил нам об исключении ZeroDivisionError – делении на ноль.

            Traceback

            В большой программе исключения часто возникают внутри. Чтобы упростить программисту понимание ошибки и причины такого поведения Python предлагает Traceback или в сленге – трэйс. Каждое исключение содержит краткую информацию, но при этом полную, информацию о месте появления ошибки. По трэйсу найти и исправить ошибку становится проще.

            Рассмотрим такой пример:

            Traceback (most recent call last): File "/home/username/Develop/test/app.py", line 862, in _handle return route.call(**args) File "/home/username/Develop/test/app.py", line 1729, in wrapper rv = callback(*a, **ka) File "/home/username/Develop/test/__init__.py", line 76, in wrapper body = callback(*args, **kwargs) File "/home/username/Develop/test/my_app.py", line 16, in index raise Exception('test exception') 

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

            Рассмотрим какие ещё встречаются комментарии к исключениям:

            >>> 2 + '1' Traceback (most recent call last): File "", line 1, in 2 + '1' TypeError: unsupported operand type(s) for +: 'int' and 'str' 

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

            >>> int('qwerty') Traceback (most recent call last): File "", line 1, in int('qwerty') ValueError: invalid literal for int() with base 10: 'qwerty' 

            Приведение строчки к целому числу приводит к исключению ValueError.

            В трэйсе этих двух примеров можно прочесть, что в таком-то файле на такой-то строчке есть ошибки.

            На этом список встроенных исключений не заканчивается, в следующем разделе рассмотрены основные исключения и причины их возникновения.

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

            Исключение, которое вы не увидите при выполнении кода – это BaseException – базовое исключение, от которого берут начало остальные.

            В иерархии исключений две основные группы:

            • Системные исключения и ошибки
            • Обыкновенные исключения

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

            К системным можно смело отнести:

            • SystemExit – исключение, порождаемое функцией sys.exit при выходе из программы.
            • KeyboardInterrupt – возникает при прерывании программы пользователем (обычно сочетанием клавиш Ctrl+C).
            • GeneratorExit — возникает при вызове метода close объекта generator.

            Остальные исключения – это "обыкновенные". Спектр уже готовых исключений велик.

            Для Python2 иерархию исключений можно представить так:

            Python 2 Exception

            Список исключений покрывает большой объем ситуаций и ошибок программиста. Если предупреждения (warning) только просят обратить внимание, то ошибки уже могут остановить исполнение программы.

            В Python3 появились новые исключения и иерархия стала такова:

            Python3 Exception

            В целом заметно, что при создании Python3 добавлен блок новых исключений. Но даже этих почти 70 исключений не хватает при написании программ на языке Python.

            Использование исключений

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

            Начнем с обработки.

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

            Давайте рассмотрим случай с делением на 0.

            >>> a = 100 >>> b = 0 >>> c = a / b 

            Данный код приведет к исключению ZeroDivisionError. Чтобы этого не случилось, воспользуемся конструкцией try..except , например, так:

            >>> try: . a = 100 . b = 0 . c = a / b . except ZeroDivisionError as e: . print(e) . division by zero 

            Если исполнить этот код, то на консоль будет выведена строка "integer division or modulo by zero". Казалось бы, что толком ничего это нам не дало, ошибка все также есть. Однако в блок except можно поместить обработку.

            Например, мы условились, что значение переменной c в случае ошибки деления равно -1. Тогда модифицируем код:

            >>> try: . a = 100 . b = 0 . c = a / b . except ZeroDivisionError as e: . c = -1 >>> c -1 

            Перед тем как идти дальше, рассмотрим ещё одну возможность.

            Пускай у нас файл с данными в файловой системе, и необходимо его прочитать. В этом случае сразу же всплывают несколько исключительных ситуаций, такие как: нет файла, файл битый, файл пустой (по заданию мы знаем, что в нём данные) и другие.

            Используя исключения, можно вот так решить эту задачу:

            try: filepath = 'test_file.txt' with open(filepath, 'r') as fio: result = fio.readlines() if not result: raise Exception("File is empty") except IOError as e: result = [] except Exception as e: result = [] print(e) 

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

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

            try: your_code except (IOError, Exception) as e: print(e) 

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

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

            На сленге программистов "бросить исключение" означает написать код, который при исполнении будет инициировать исключительную ситуацию.

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

            Чтобы бросить исключение необходимо воспользоваться raise

            raise IOError("текст исключения") 

            где IOError это класс исключения.

            Если при обработке исключения вы желаете пробросить его ещё выше, то следует написать такой код:

            try: your_code except Exception as e: raise 

            Собственные исключения

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

            В минимальном исполнении необходимо наследоваться от какого-нибудь класса в иерархии исключений. Например так:

            class MyException(Exception): pass 

            Тогда можно бросить своё исключение:

            raise MyException(Exception) 

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

            Как правило, исключения это очень маленькие классы. Они должны выполняться максимально быстро.

            Дополнение: Полная форма try..except

            Форма try. except не полная, полной же является try..except..else..finally .

            Применение полной конструкции может заметно упростить код, а также сделать его более безопасным.

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

            Иными словами, finally выполняет блок инструкций в любом случае, было ли исключение, или нет. А инструкция else выполняется в том случае, если исключения не было.

            В целом, использование полной формы таково:

            try: исполяем какой-то код except Exception as e: обработка исключения else: код, который будет исполнен в случае, когда не возникает исключения finally: код, который гарантированно будет исполнен последним (всегда исполняется) 

            Выводы

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

            • Что такое исключение
            • Какие типы исключений присутствуют в языке
            • Как обрабатывать исключения
            • Как вызвать исключения
            • Как создавать собственные исключения

            Аватары экспертов Хекслета

            Остались вопросы? Задайте их в разделе «Обсуждение»

            Вам ответят команда поддержки Хекслета или другие студенты

            Об обучении на Хекслете

            • Статья «Как учиться и справляться с негативными мыслями»
            • Статья «Ловушки обучения»
            • Статья «Сложные простые задачи по программированию»
            • Вебинар « Как самостоятельно учиться »

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

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

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

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

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

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