Обработка исключений
Обработка исключений в Python 3 является мощным механизмом по управлению программой в особых ситуациях. Он позволяет избежать ее аварийного завершения вследствие внезапных и непредвиденных ошибок. Такая возможность реализована в языке программирования Python при помощи специальных синтаксических конструкций, позволяющих отлавливать, а затем обрабатывать исключения для того, чтобы программа всегда выполняла заданный алгоритм.
Что такое исключения?
Разработка программы на любом языке довольно часто бывает связана с возникновением различного рода ошибок, препятствующих получению желаемого результата. Как правило, не все они приводят к моментальному завершению программы: некоторые ошибки можно ликвидировать еще на этапе компиляции, другие же способны оставаться незамеченными достаточно долгое время, а третьи и вовсе не зависят от программиста и возникают лишь в определенных ситуациях.
На сегодняшний день принято выделять такие типы ошибок:
- Синтаксические – возникают из-за синтаксических погрешностей кода;
- Логические – проявляются вследствие логических неточностей в алгоритме;
- Исключения – вызваны некорректными действиями пользователя или системы.
Синтаксические ошибки являются следствием несоблюдения общепринятых норм языка, например, пропуска круглой скобки в предполагаемом месте или некорректного написания имени функции. Такие погрешности успешно отлавливаются компилятором, который сразу же сообщает пользователю о проблеме в написанном коде. Следующий пример показывает, что будет, если пропустить символ двойных кавычек при создании строкового литерала:
После попытки запуска выдастся текст ошибки:
Логические ошибки считаются более сложными в выявлении, поскольку не отлавливаются ни на этапе компиляции, ни во время выполнения готовой программы. Обычно они вызваны определенными недостатками в логике написанного алгоритма, из-за чего пользователь не получает желаемого результата. Ниже показана работа функции, которая должна вычислять среднее значение двух чисел, однако она этого не делает из-за неправильной формулы:
Исключения представляют собой еще один вид ошибок, который проявляется в зависимости от наличия обстоятельств, меняющих ход выполнения программы. Примером этому вполне может быть ввод некорректного значения либо отсутствие нужного файла. Как правило, все доступные виды исключений становятся видимыми во время выполнения программы. Далее продемонстрирован пример, показывающий невозможность операции деления на ноль:
После попытки запуска будет выведено:
Как можно заметить из результатов выполнения программы, деление на ноль провоцирует исключительную ситуацию, которая приводит к аварийному завершению работы и выводу ошибки на экран. В данном случае отображается файл, а также номер строки кода, где было выброшено исключение ZeroDivisionError. Ниже приводится краткое описание проблемы.
Перехват исключений
Для того, чтобы исключение не приводило к внезапному завершению программы, его стоит обработать. Для этого есть специальный механизм, предотвращающего все непредвиденные ситуации. Это поможет избежать сбоев в работе написанного алгоритма за счет расширения его возможностей, позволяющих действовать согласно новым обстоятельствам. Но сначала попробуем запустить программу, которая попытается открыть обычный текстовый файл:
После запуск будет выведено:
Так как файла с таким именем на жестком диске не обнаружено, программа сгенерировала исключение FileNotFoundError, сообщающее о проблеме с вводом/выводом. Последняя строка кода, в которой обозначается завершение программы, не была отображена на экране. Это значит, что не все операции, предусмотренные алгоритмом, были выполнены из-за проявившегося исключения.
Рассмотрим пример в Python конструкции try-except. Она позволяет обработать исключительную ситуацию без необходимости завершения уже работающей программы:
Как видно из кода выше, блок try содержит опасный код, способный привести к ошибке (отсутствие нужного файла), а блок except включает в себя инструкции, которые следует выполнить в случае возникнувшей проблемы. Теперь если требуемый файл не был найден, программа не станет завершаться, о чем свидетельствует последний вывод функции print.
Несколько блоков except
Блоков except может быть несколько, в зависимости от того, какой тип исключения нужно обработать. Как правило, сначала обрабатываются более частные случаи, а затем общие:
Вложенные блоки и else
Блоки try-except могут быть вложенными для более гибкого управления исключениями. В следующем примере демонстрируется попытка открыть текстовый файл и записать в него некую строку. Для каждой цели используется отдельный блок try.
В данном случае — else сработает при успешной операции write. По умолчанию файл открывается на чтение в текстовом режиме. Поэтому при открытии файла будем использовать режим «w». В этом режиме файл открывается на запись. Если файла не было — создается новый, если был — перезаписывается.
finally
Бывают ситуации, когда некие важные действия необходимо совершить вне зависимости от того, было вызвано исключение или нет. Для этого используется блок finally, содержащий набор инструкций, которые нужно выполнить в любом случае. Следующий пример улучшает работу предыдущей программы, добавляя в нее возможность закрывать текстовый файл:
Иногда такой подход к работе с текстовыми файлами может показаться слишком сложным, так как код, который его реализует, выглядит громоздким. Специально для этого существует конструкция with/as, позволяющая автоматизировать некоторые методы, такие как закрытие файла у соответствующего объекта. Таким образом, сокращается длина написанного кода:
Как и во всех предыдущих случаях, программа, которая способна правильно обработать все возникающие типы исключений, всегда завершается естественным образом, без прерываний заданного алгоритма. Это значительно повышает комфорт и безопасность ее использования.
Управление исключениями
Python позволяет создавать пользовательские исключения. Так же рассмотрим логирование программы.
Пользовательские исключения
Как правило, исключения автоматически вызываются в нужных ситуациях, однако в Python присутствует возможность запускать их самостоятельно. Для этого применяется ключевое слово raise. Следом за ним необходимо создать новый объект типа Exception, который потом можно обработать при помощи привычных конструкций try-except, как в данном примере:
Чтобы описать собственный тип исключения, нужно создать новый класс, унаследованный от базового типа Exception. Это позволит запускать особые виды исключений в ситуациях, когда поведение пользователя не соответствует алгоритму программы. В конструкторе Exception указываем текст исключения. После того, как оно сработало и было перехвачено, можно его получить с помощью str.
В следующем коде показан процесс генерации исключения NegativeAge, которое не позволяет пользователю ввести отрицательный возраст. Таким образом, экран выдает соответствующую ошибку:
Запись в лог
Для вывода специальных сообщений, не влияющих на функционирование программы, в Python применяется библиотека логов. Чтобы воспользоваться ею, необходимо выполнить импорт в верхней части файла. Существует несколько типов логов, отобразить которые поможет команда, определенная во второй строке кода в следующем примере программы:
Как видно из результатов выполнения программы, пользователю доступны разные типы сообщений, такие как предупреждение, информация или ошибка. Обычно они применяются при разработке программного обеспечения, чтобы не выводить лишний текст в консоль.
С помощью logging на Python можно записывать в лог и исключения. Обычно лог пишется в файл, зададим его как log.txt. Уровень INFO указывает, что сообщения уровней ниже (в данном случае debug) не будут отражаться в логе. Python позволяет в try-except получить текст ошибки, который и запишем:
В log .txt будет добавлена строка сообщения о типе сработавшего исключения «ERROR:root:division by zero».
Иерархия исключений
В языке программирования Python присутствует строгая иерархия исключений. Вершиной является BaseException, включающий в себя все существующие разновидности исключений:
- SystemExit – возникает при выходе из программы с помощью sys.exit;
- KeyboardInterrupt – указывает на прерывание программы пользователем;
- GeneratorExit – появляется при вызове метода close для объекта generator;
- Exception – представляет совокупность обычных несистемных исключений.
Перечень несистемных исключений, которые содержит в себе класс Exception приведены в следующей таблице. Все они актуальны для последней на данный момент версии Python 3.
Название | Характеристика |
ArithmeticError | Порождается арифметическими ошибками (операции с плавающей точкой, переполнение числовой переменной, деление на ноль) |
AssertionError | Возникает при ложном выражении в функции assert |
AttributeError | Появляется в случаях, когда нужный атрибут объекта отсутствует |
BufferError | Указывает на невозможность выполнения буферной операции |
EOFError | Проявляется, когда функция не смогла прочитать конец файла |
ImportError | Сообщает о неудачном импорте модуля либо атрибута |
LookupError | Информирует про недействительный индекс или ключ в массиве |
MemoryError | Возникает в ситуации, когда доступной памяти недостаточно |
NameError | Указывает на ошибку при поиске переменной с нужным именем |
NotImplementedError | Предупреждает о том, что абстрактные методы класса должны быть обязательно переопределены в классах-наследниках |
OSError | Включает в себя системные ошибки (отсутствие доступа к нужному файлу или директории, проблемы с поиском процессов) |
ReferenceError | Порождается попыткой доступа к атрибуту со слабой ссылкой |
RuntimeError | Сообщает об исключении, которое не классифицируется |
StopIteration | Возникает во время работы функции next при отсутствии элементов |
SyntaxError | Представляет собой совокупность синтаксических ошибок |
SystemError | Порождается внутренними ошибками системы |
TypeError | Указывает на то, что операция не может быть выполнена с объектом |
UnicodeError | Сообщает о неправильной кодировке символов в программе |
ValueError | Возникает при получении некорректного значения для переменной |
Warning | Обозначает предупреждение |
Заключение
Исключения являются самостоятельным типом данных, при помощи которого программа сообщает пользователю о различных ошибках. Обработка исключений позволяет менять сценарий выполнения программы с учетом обстоятельств, так или иначе блокирующих ее нормальную работу. Для удобного управления исключениями в языке программирования Python предусмотрены специальные синтаксические конструкции. Кроме того, в нем есть большая библиотека готовых исключений, а также возможность создавать собственные.
Источник
Исключения в python. Конструкция try — except для обработки исключений
Исключения (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 — деление на ноль.
- AssertionError — выражение в функции assert ложно.
- AttributeError — объект не имеет данного атрибута (значения или метода).
- BufferError — операция, связанная с буфером, не может быть выполнена.
- EOFError — функция наткнулась на конец файла и не смогла прочитать то, что хотела.
- ImportError — не удалось импортирование модуля или его атрибута.
- LookupError — некорректный индекс или ключ.
- IndexError — индекс не входит в диапазон элементов.
- KeyError — несуществующий ключ (в словаре, множестве или другом объекте).
- MemoryError — недостаточно памяти.
- NameError — не найдено переменной с таким именем.
- UnboundLocalError — сделана ссылка на локальную переменную в функции, но переменная не определена ранее.
- OSError — ошибка, связанная с системой.
- BlockingIOError
- ChildProcessError — неудача при операции с дочерним процессом.
- ConnectionError — базовый класс для исключений, связанных с подключениями.
- BrokenPipeError
- ConnectionAbortedError
- ConnectionRefusedError
- ConnectionResetError
- FileExistsError — попытка создания файла или директории, которая уже существует.
- FileNotFoundError — файл или директория не существует.
- InterruptedError — системный вызов прерван входящим сигналом.
- IsADirectoryError — ожидался файл, но это директория.
- NotADirectoryError — ожидалась директория, но это файл.
- PermissionError — не хватает прав доступа.
- ProcessLookupError — указанного процесса не существует.
- TimeoutError — закончилось время ожидания.
- ReferenceError — попытка доступа к атрибуту со слабой ссылкой.
- RuntimeError — возникает, когда исключение не попадает ни под одну из других категорий.
- NotImplementedError — возникает, когда абстрактные методы класса требуют переопределения в дочерних классах.
- SyntaxError — синтаксическая ошибка.
- IndentationError — неправильные отступы.
- TabError — смешивание в отступах табуляции и пробелов.
- IndentationError — неправильные отступы.
- SystemError — внутренняя ошибка.
- TypeError — операция применена к объекту несоответствующего типа.
- ValueError — функция получает аргумент правильного типа, но некорректного значения.
- UnicodeError — ошибка, связанная с кодированием / раскодированием unicode в строках.
- UnicodeEncodeError — исключение, связанное с кодированием unicode.
- UnicodeDecodeError — исключение, связанное с декодированием unicode.
- UnicodeTranslateError — исключение, связанное с переводом unicode.
- Warning — предупреждение.
Теперь, зная, когда и при каких обстоятельствах могут возникнуть исключения, мы можем их обрабатывать. Для обработки исключений используется конструкция try — except.
Первый пример применения этой конструкции:
В блоке try мы выполняем инструкцию, которая может породить исключение, а в блоке except мы перехватываем их. При этом перехватываются как само исключение, так и его потомки. Например, перехватывая ArithmeticError, мы также перехватываем FloatingPointError, OverflowError и ZeroDivisionError.
Также возможна инструкция except без аргументов, которая перехватывает вообще всё (и прерывание с клавиатуры, и системный выход и т. д.). Поэтому в такой форме инструкция except практически не используется, а используется except Exception. Однако чаще всего перехватывают исключения по одному, для упрощения отладки (вдруг вы ещё другую ошибку сделаете, а except её перехватит).
Ещё две инструкции, относящиеся к нашей проблеме, это finally и else. Finally выполняет блок инструкций в любом случае, было ли исключение, или нет (применима, когда нужно непременно что-то сделать, к примеру, закрыть файл). Инструкция else выполняется в том случае, если исключения не было.
Источник