Что такое Python Exception As E: обработка исключений и оператор try-except

0
121

Памятка по обработке исключений в Python

  1. Используйте try-except для обработки потенциальных ошибок в коде.
  2. Всегда указывайте конкретный тип исключения в except, избегайте голого except.
  3. Применяйте as e для доступа к объекту ошибки и её атрибутам.
  4. Используйте блок else для кода, который выполняется только при отсутствии исключений.
  5. Применяйте блок finally для освобождения ресурсов (закрытие файлов, соединений).
  6. Не подавляйте исключения без необходимости — логируйте их или пробрасывайте дальше.
  7. Для получения полной информации об ошибке используйте модуль traceback.
  8. Группируйте родственные исключения в кортежи для компактной обработки.
  9. Создавайте собственные классы исключений для специфических ошибок приложения.
  10. Тестируйте обработку исключений с помощью модуля unittest или pytest.

Ошибки и исключения

Урок 31 - изображение номер один
Урок 31 — изображение номер один

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

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

В терминологии языка Python здесь возникло исключение, принадлежащее классу SyntaxError. Согласно документации Python синтаксические ошибки все-таки принято относить к ошибкам, а все остальные — к исключениям. В некоторых языках программирования не используется слово «исключение», а ошибки делят на синтаксические и семантические (логические). Нарушение семантики обычно означает, что, хотя выражения написаны верно с точки зрения синтаксиса языка, программа не работает так, как от нее ожидалось. Для сравнения. Вы можете грамотным русским языком сказать несколько предложений, но по смыслу это будет белиберда, или вас поймут не так, как вы думали.

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

Если вы попытаетесь обратиться к переменной, которой не было присвоено значение, что в случае Python означает, что переменная вообще не была объявлена, она не существует, то возникнет исключение NameError.

Последнюю строку сообщения можно перевести как «Ошибка имени: имя ‘b’ не определено».

Если исключение возникает при выполнении кода из файла, то вместо line 1 будет указана строка, в которой оно возникло, например, line 24. Вместо <stdin> будет указано имя файла, например,. В данном же случае stdin обозначает стандартный поток ввода. По-умолчанию это поток ввода с клавиатуры. Строка 1 — потому что в интерактивном режиме каждое выражение интерпретируется отдельно, как обособленная программка. Если написать выражение, состоящее из нескольких строк, то линия возникновения ошибки может быть другой:

Следующие два исключения, о которых следует упомянуть, и с которыми вы уже могли встретиться в предыдущих уроках, это ValueError и TypeError – ошибка значения и ошибка типа.

>>> int(«Hi») Traceback (most recent call last): File «<stdin>», line 1, in <module> ValueError: invalid literal for int() with base 10: ‘Hi’ >>> >>> 8 + «3» Traceback (most recent call last): File «<stdin>», line 1, in <module> TypeError: unsupported operand type(s) for +: ‘int’ and ‘str’

В примере строку «Hi» нельзя преобразовать к целому числу. Возникает исключение ValueError, потому что функция int() не может преобразовать такое значение.

Число 8 и строка «3» принадлежат разным типам, операнд сложения между которыми в Python не поддерживается. При попытке их сложить возникает исключение TypeError.

Обработка исключений. Оператор try-except

Try except to catch exceptions in - изображение номер два
Try except to catch exceptions in — изображение номер два

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

ЧИТАТЬ ТАКЖЕ:  Цикл for in range 1 6 print Python Rocks: сколько итераций и функция range

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

В Питоне такой перехват выполняет оператор try-except. «Try» переводится как «попытаться», «except» — как исключение. Словами описать его работу можно так: «Попытаться сделать вот это. Если при этом возникло исключение, то сделать что-то другое.» Его конструкция (но не логика работы) похожа на условный оператор с веткой else. Рассмотрим пример:

Исключительная ситуация может возникнуть в третьей строчке кода, когда значение переменной n преобразуется к целому числу. Если это невозможно, то дальнейшее выполнение выражений в теле try прекращается. В данном случае выражение print(«Удачно») выполнено не будет. При этом поток выполнения программы перейдет на ветку except и выполнит ее тело.

Если в теле try исключения не возникает, то тело ветки except не выполняется.

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

try: n = input(«Введите целое число: «) n = int(n) print(«Все нормально. Вы ввели число», n) except ValueError: print(«Вы ввели не целое число»)

Теперь если сработает тело except мы точно знаем, из-за чего возникла ошибка. Но если в теле try возникнет еще какое-нибудь исключение, то оно не будет обработано. Для него надо написать отдельную ветку except. Рассмотрим программу:

try: a = float(input(«Введите делимое: «)) b = float(input(«Введите делитель: «)) c = a / b print(«Частное: %.2f» % c) except ValueError: print(«Нельзя вводить строки») except ZeroDivisionError: print(«Нельзя делить на ноль»)

При ее выполнении исключения могут возникнуть в трех строчках кода: где происходит преобразование введенных значений к вещественным числам и в месте, где происходит деление. В первом случае может возникнуть ValueError, во втором — ZeroDivisionError. Каждый тип исключения обрабатывается своей веткой except.

Несколько исключений можно сгруппировать в одну ветку и обработать совместно:

У оператора обработки исключений, кроме except, могут быть еще ветки finally и else (не обязательно обе сразу). Тело finally выполняется всегда, независимо от того, выполнялись ли блоки except в ответ на возникшие исключения или нет. Тело else сработает, если исключений в try не было, то есть не было переходов на блоки except.

try: n = input(«Введите целое число: «) n = int(n) except ValueError: print(«Неверный ввод») else: # выполняется, когда в блоке try не возникло исключений print(«Все нормально. Вы ввели число», n) finally: # выполняется в любом случае print(«Конец программы»)

Примечание. В данном коде используются комментарии. В языке Python перед ними ставится знак решетки #. Комментарии в программном коде пишутся исключительно для человека и игнорируются интерпретатором или компилятором.

Посмотрите, как выполняется программа в случае возникновения исключения и без этого:

Также исключение может возникнуть в блоке except, else или finally, и тогда им нужен собственный обработчик. Модифицируем немного предыдущую программу и специально сгенерируем исключение в теле except:

try: n = input(«Введите целое число: «) n = int(n) except ValueError: print(«Неверный ввод») 3 / 0 except ZeroDivisionError: print(«Деление на ноль») else: print(«Все нормально. Вы ввели число», n) finally: print(«Конец программы»)

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

Введите целое число: а Неверный ввод Конец программы Traceback (most recent call last): File «», line 15, in <module> n = int(n) ValueError: invalid literal for int() with base 10: ‘а’ During handling of the above exception, another exception occurred: Traceback (most recent call last): File «», line 6, in <module> 3 / 0 ZeroDivisionError: division by zero

ЧИТАТЬ ТАКЖЕ:  Python print: как печатать без перехода на новую строку

Мало того, что не было обработано деление на ноль, поскольку тело except ValueError неудачно завершилось, само исключение ValueError посчиталось необработанным. Решение проблемы может быть, например, таким:

… except ValueError: print(«Неверный ввод») try: 3 / 0 except ZeroDivisionError: print(«Деление на ноль»)…

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

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

Обработка исключений. Оператор try-except

Master - изображение номер три
Master — изображение номер три

Еще один совет, который убережет от лишнего кода — это использование метода ().

Не нужно регистрировать объект исключения. Метод () предназначен для использования «как есть» внутри блоков except. Он уже обрабатывает трассировку стека с информацией о выполнении и отображает, какое исключение его вызвало, с его сообщением, установленным на уровень ERROR!

Обработка исключений. Оператор try-except

В питоне существует около 60 классов встроенных исключений. Самые популярные с примерами причин их возникновения:

  • ZeroDivisionError — деление на ноль.
  • AssertionError — проверка внутри assert не выполнена.
  • EOFError — в ходе считывания данных обнаружен EOF.
  • ImportError — не получилось импортировать модуль.
  • IndexError — обращение к элементу вне диапазона.
  • KeyboardInterrupt — пользователь прервал процесс комбинацией клавиш.
  • KeyError — обращение к отсутствующему ключу в контейнере.
  • MemoryError — исчерпание свободной памяти.
  • NameError — глобальное или локальное имя не найдено.
  • RuntimeError — ошибка времени выполнения (в том числе использование не объявленной переменной).
  • SyntaxError — синтаксическая ошибка в коде программы.
  • SystemError — ошибка работы интерпретатора.
  • TypeError — прибавление числа к строке.
  • ValueError — передача в функцию аргумента ожидаемого типа, но с неправильным значением.

Часто задаваемые вопросы об обработке исключений в Python

Вопрос: Что означает конструкция except Exception as e?
Ответ: Это перехват любого исключения, наследуемого от класса Exception, с сохранением объекта ошибки в переменную e для дальнейшего анализа.

Вопрос: Чем отличается except: от except Exception as e?
Ответ: Голый except перехватывает абсолютно все исключения, включая системные (например, SystemExit). except Exception as e перехватывает только исключения, связанные с работой программы, и позволяет получить доступ к объекту ошибки.

Вопрос: Можно ли использовать as e без указания типа исключения?
Ответ: Да, можно написать except Exception as e, но нельзя просто except as e — это синтаксическая ошибка.

Вопрос: Как вывести сообщение об ошибке через as e?
Ответ: Используйте print(e) или str(e) внутри блока except. Объект e содержит текстовое описание ошибки.

Вопрос: Что такое traceback и как его получить через as e?
Ответ: Traceback — это полный стек вызовов. Для его получения используйте модуль traceback: traceback.print_exc() или traceback.format_exc().

Вопрос: Можно ли перехватить несколько исключений в одном except?
Ответ: Да, через кортеж: except (ValueError, TypeError) as e.

Вопрос: Как получить имя класса исключения через as e?
Ответ: Используйте type(e).__name__ — это вернет строку с именем класса, например ‘ValueError’.

Вопрос: Что произойдет, если не использовать as e?
Ответ: Вы не сможете получить доступ к объекту исключения и его атрибутам (сообщение, код ошибки и т.д.).

Вопрос: Как правильно логировать ошибки с as e?
Ответ: Используйте модуль logging: logging.error(‘Ошибка: %s’, e) или logging.exception(‘Ошибка’) для автоматического добавления traceback.

Вопрос: Можно ли использовать as e в блоке finally?
Ответ: Нет, переменная e определена только внутри блока except. В finally она недоступна.