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

автор

Что вы предпринимаете, когда с работой вашей программы что-то идет не так? Допустим, вы пытаетесь открыть файл, но вы ввели неверный путь, или вы хотите узнать информацию у пользователей и они пишут какую-то бессмыслицу. Вы не хотите, чтобы ваша программа крэшилась, по-этому вы выполняете обработку исключений. В Пайтоне, конструкция всегда обернута в то, что называется try/except. В данном разделе мы рассмотрим следующие понятия:

  • Базовые типы исключений;
  • Обработка исключений при помощи try/except;
  • Узнаем, как работает try/except/finally;
  • Выясним, как работает оператор else совместно с try/except;

Начнем со знакомства с самыми обычными исключениями, которые вы увидите в Пайтоне. Обратите внимание на то, что ошибка и исключение – два разных слова, описывающие одно и то же, в контексте обработки исключений.

Основные исключения

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

  • Exception – то, на чем фактически строятся все остальные ошибки;
  • AttributeError – возникает, когда ссылка атрибута или присвоение не могут быть выполнены;
  • IOError – возникает в том случае, когда операция I/O (такая как оператор вывода, встроенная функция open() или метод объекта-файла) не может быть выполнена, по связанной с I/O причине: «файл не найден», или «диск заполнен», иными словами.
  • ImportError – возникает, когда оператор import не может найти определение модуля, или когда оператор не может найти имя файла, который должен быть импортирован;
  • IndexError – возникает, когда индекс последовательности находится вне допустимого диапазона;
  • KeyError – возникает, когда ключ сопоставления (dictionary key) не найден в наборе существующих ключей;
  • KeyboardInterrupt – возникает, когда пользователь нажимает клавишу прерывания(обычно Delete или Ctrl+C);
  • NameError – возникает, когда локальное или глобальное имя не найдено;
  • OSError – возникает, когда функция получает связанную с системой ошибку;
  • SyntaxError — возникает, когда синтаксическая ошибка встречается синтаксическим анализатором;
  • TypeError – возникает, когда операция или функция применяется к объекту несоответствующего типа. Связанное значение представляет собой строку, в которой приводятся подробные сведения о несоответствии типов;
  • ValueError – возникает, когда встроенная операция или функция получают аргумент, тип которого правильный, но неправильно значение, и ситуация не может описано более точно, как при возникновении IndexError;
  • ZeroDivisionError – возникает, когда второй аргумент операции division или modulo равен нулю;

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

Как обрабатывать исключения?

Обработка исключений в Пайтон – это очень просто. Потратим немного времени и напишем несколько примеров, которые их вызовут. Мы начнем с одной из самых элементарных проблем: деление на ноль.

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

«Голое» исключение

Есть еще один способ поймать ошибку:

Но мы его не рекомендуем. На жаргоне Пайтона, это известно как голое исключение, что означает, что будут найдены вообще все исключения. Причина, по которой так делать не рекомендуется, заключается в том, что вы не узнаете, что именно за исключение вы выловите. Когда у вас возникло что-то в духе ZeroDivisionError, вы хотите выявить фрагмент, в котором происходит деление на ноль. В коде, написанном выше, вы не можете указать, что именно вам нужно выявить. Давайте взглянем еще на несколько примеров:

В первом примере, мы создали словарь из трех элементов. После этого, мы попытались открыть доступ ключу, которого в словаре нет. Так как ключ не в словаре, возникает KeyError, которую мы выявили. Второй пример показывает список, длина которого состоит из пяти объектов. Мы попытались взять седьмой объект из индекса.

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

Это самый стандартный способ выявить несколько исключений. Сначала мы попробовали открыть доступ к несуществующему ключу, которого нет в нашем словаре. При помощи try/except мы проверили код на наличие ошибки KeyError, которая находится во втором операторе except. Обратите внимание на то, что в конце кода у нас появилась «голое» исключение. Обычно, это не рекомендуется, но вы, возможно, будете сталкиваться с этим время от времени, так что лучше быть проинформированным об этом. Кстати, также обратите внимание на то, что вам не нужно использовать целый блок кода для обработки нескольких исключений. Обычно, целый блок используется для выявления одного единственного исключения. Изучим второй способ выявления нескольких исключений:

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

В зависимости от сложности данной ошибки, вам может понадобиться выйти из программы. Иногда вам может понадобиться выполнить очистку, перед выходом из программы. Например, если вы открыли соединение с базой данных, вам нужно будет закрыть его, перед выходом из программы, или вы можете закончить с открытым соединением. Другой пример – закрытие дескриптора файла, к которому вы обращаетесь. Теперь нам нужно научиться убирать за собой. Это очень просто, если использовать оператор finally.

Оператор finally

Оператор finally очень прост в использовании. Давайте взглянем на нижеизложенный пример:

Если вы запустите это код, оно отобразиться и в операторе except и в finally. Весьма просто, не так ли? Теперь вы можете использовать оператор finally, чтобы убрать за собой. Вы можете также вписать код exit в конце оператора finally.

Попробуйте except или else

Оператор try/except также имеет пункт else. Он работает только в том случае, если в вашем коде нет ни единой ошибки. Давайте потратим немного времени и взглянем на парочку примеров:

Мы видим словарь, состоящий из трех элементов, и в операторе try/except мы открываем доступ к существующему ключу. Это работает, так что ошибка KeyError не возникает. Так как ошибки нет, else работает, и надпись“No error occurred!” появляется на экране. Теперь добавим оператор finally:

В данном коде работают и оператор else и finally. Большую часть времени вы не будете сталкиваться с оператором else, используемый в том или ином коде, который следует за оператором try/except, если ни одна ошибка не была найдена. Единственное полезное применение оператора else, которое я видел, это когда вы хотите запустить вторую часть кода, в которой может быть ошибка. Конечно, если ошибка возникает в else, то она не будет поймана.

Подведем итоги

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

Вам может быть интересно

Scroll Up