0 знаков
37. Обработка исключений (try/except) в Python
Кратко- В Python обработка исключений необходима для предотвращения остановки программы при возникновении ошибок.
- Исключения в Python подразделяются на группы:
BaseException
,Exception
,ArithmeticError
,AssertionError
,AttributeError
,BufferError
,EOFError
,ImportError
,LookupError
,OSError
,RuntimeError
,StopIteration
,SyntaxError
,SystemError
,TypeError
,ValueError
,Warning
.- Конструкция
try/except
в Python позволяет "отлавливать" исключения и выполнять код в зависимости от типа исключения.- Ключевое слово
as
в Python помогает узнать, какое исключение было поднято.- Ключевое слово
raise
используется для генерации исключений.- Утверждение
assert
в Python используется для проверки истинности утверждений и возбуждения исключенияAssertionError
при ложном результате.
Введение
В предыдущем уроке вы познакомились с циклами while/else
и for/else
. В этом уроке разберем, как обрабатывать исключения, вызываемые интерпретатором Python. Уверен, вы писали код, который отлично работал, но при вводе определенных данных, например, строки вместо числа, программа останавливалась и выдавала ошибку. Это генерировалось исключение и, так как вы его не обрабатывали, работа программы прекращалась.
Давайте целенаправленно вызовем исключение ZeroDivisionError
. Если вы разделите любое число на ноль, то получите подобную ошибку:
Traceback (most recent call last):
File "C:/test.py", line 1, in <module>
print(5/0)
ZeroDivisionError: division by zero
Этим сообщением интерпретатор Python нам говорит об ошибке в первой строке файла test.py
, а точнее, в выражении print(5/0)
. В последней строке ошибки содержится название исключения и ее краткое описание.
Иерархия исключений в Python
Теперь кратко рассмотрим некоторые из исключений, которые могут возникнуть в языке Python. Сразу оговорюсь, нет необходимости запоминать все эти исключения, так как всегда их можно посмотреть в справочнике или здесь. С другой стороны, знание возможных ошибок поможет их предвидеть и не допустить. Материал этого раздела находится под спойлером, так как получился объемным.
BaseException
– это базовое исключение, от него берут начало все остальные исключения.
В базовое исключение входят:
GeneratorExit
: будет вызвано в случае применения методаclose
, объектаgenerator
.SystemExit
: будет вызвано функциейsys.exit
в случае выхода из программы.KeyboardInterrupt
: будет вызвано, если пользователь нажал сочетание клавишCtrl + C
в консоли.Exception
: в отличие от предыдущих, это группа не системных исключений, а «пользовательских», если так можно выразиться.
Исключения Exception
Группа исключений Exception
подразделяется на следующие:
Группа исключений ArithmeticError
Исключения, связанные с арифметическими ошибками. Исключение FloatingPointError
связано с выполнением неудачной операции с плавающей точкой. Исключение OverflowError
возникает, когда результат арифметической операции слишком большой и не может быть представлен. Исключение ZeroDivisionError
возникает из-за деления на ноль. Для примера, следующий код не будет работать, так как будет вызвано исключение OverflowError
:
pi = 0
for k in range(350):
pi += 16.**k
print(pi)
Исключение AssertionError
Вызывается, если результат проверки инструкции assert
является ложным. Например:
assert 1 == 0
К инструкции assert
мы еще вернемся.
Исключение AttributeError
Возникает, если у объекта нет такого атрибута или в случае ошибки доступа к нему. Например:
a = 10
a.atr
Так как переменная (объект) a не имеет атрибута atr
, то будет вызвано исключение:
Traceback (most recent call last):
File "C:/test.py", line 2, in <module>
a.atr()
AttributeError: 'int' object has no attribute 'atr'
Исключение BufferError
Возникает, когда операция с буфером не может быть выполнена по тем или иным причинам. Например, буфер не доступен для записи, так как работает только в режиме «для чтения».
Исключение EOFError
Возникает, когда программа обнаруживает конец файла, то есть маркер EOF
в процессе считывания данных.
Исключение ImportError
Возникает, если вы попробуете подключить несуществующий модуль при помощи инструкции import
или отсутствующий атрибут.
Группа исключений LookupError
Исключение IndexError
вызывается, если используемый индекс выходит за диапазон, например, обратимся к четвертому списка из трех элементов:
a = [1, 2, 3]
a[3]
Исключение KeyError
возникает, если вы обратились к несуществующему ключу:
a = {'1': 1, '2': 2, '3': 3}
a['4']
Исключение MemoryError
Возникает, если закончилась память при выполнении операции.
Исключение NameError
Возникает, если не найдено имя переменной, функции или другого объекта, например:
print(a)
Результат:
Traceback (most recent call last):
File "C:/test.py", line 1, in <module>
print(a)
NameError: name 'a' is not defined
Группа исключений OSError
Большая по своему составу группа исключений, связанных с системой.
В нее входит исключение BlockingIOError
, которое поднимается, когда блокируется ввод/вывод. Исключение ChildProcessError
возникает при неудачной операции с дочерним процессом. Исключение ConnectionError
является еще одной группой, связанной с проблемами подключения. Исключение FileExistsError
будет поднято, если вы попытаетесь создать уже существующий файл или директорию. Исключение FileNotFoundError
возникнет, если вы обратитесь к несуществующему файлу или директории. Если системный вызов был прерван каким-либо входящим сигналом, то поднимется исключение InterruptedError
. Исключение IsADirectoryError
возникнет, если интерпретатор Python ожидал файл, но это оказалась директория. Исключение NotADirectoryError
является противоположным предыдущему. Если возникли проблемы с правами доступа, то поднимется исключение PermissionError
. Исключение ProcessLookupError
возникнет, если такого процесса не существует, а TimeoutError
, если закончилось время ожидания.
Исключение ReferenceError
Исключение ReferenceError
поднимается в случае обращения к атрибуту объекта с помощью слабой ссылки. Тема про слабые ссылки не такая простая, но, возможно, мы к ней вернемся. Если кратко: слабые ссылки нужны для организации хэш-таблиц из «увесистых» объектов. За работу слабых ссылок отвечает модуль weakref
.
Исключение RuntimeError
Такое исключение возникает в связи с ошибкой времени исполнения не попадающей под другие категории. До версии Python 3.5. под это исключение попадала бесконечная рекурсия, однако сейчас под это выделен новый тип исключений: RecursionError
.
Исключение StopIteration
Поднимается функцией next
, если в итераторе закончились элементы. Про итераторы мы поговорим в последующих уроках.
Исключение SyntaxError
Наверное, с исключением SyntaxError
вы будете встречаться чаще всего. Оно поднимается парсером в случае нахождения синтаксических ошибок в исходном коде.
Исключение SystemError
Поднимается, когда возникают внутренние ошибки на уровне интерпретатора.
Исключение TypeError
Исключение TypeError
поднимается при попытке обработки объекта, для которого такие действия неприменимы. Например, сложение строки и числа:
print('Hello' + 20)
Если вы забыли, что язык Python является сильно типизированным, то вернитесь к уроку про типы данных.
Исключение ValueError
Возникает, когда в функцию передан неправильный аргумент, т.е. тип переданного аргумента правильный, а значение не поддерживается.
Группа исключений Warning
Исключения группы Warning
связаны с различными категориями предупреждений.
Конструкция try/except в Python
Настало время перейти к конструкции, которая позволяет «отлавливать» исключения в Python. Предположим, у нас есть программа, на вход которой поступает два числа, после чего одно делится на другое.
a, b = int(input()), int(input())
print(a / b)
Вы уже знаете, что при определенных входных данных, программа завершится. Конечно, от деления на ноль можно защититься при помощи условной конструкции if:
a, b = int(input()), int(input())
if (b != 0):
print(a / b)
else:
print("b равно 0")
Перепишем этот пример с использованием инструкции try/except
:
try:
a, b = int(input()), int(input())
print(a / b)
except ZeroDivisionError:
print("b равно 0")
Как же работает инструкция try/except
? Сначала будет выполнено выражение, которое расположено в блоке try
. Если внутри блока try
не возникло никаких исключений, то блок except
пропускается и выполняется дальнейший код.
Если все же внутри блока try
возникло исключение, то оставшийся код в этом блоке пропускается и выполняется код в блоке except
и управление передается следующей инструкции после этого блока. Например, следующая программа завершится корректно, даже при делении на ноль:
try:
a, b = int(input()), int(input())
print(a / b)
except ZeroDivisionError:
print("b равно 0")
print("Конец программы")
Однако если в блоке try
поднялось исключение, тип которого не указан в блоке except
, программа прервется и будет выдана ошибка. Блоков except
может быть несколько:
try:
a, b = int(input()), int(input())
print(a / b)
except ZeroDivisionError:
print("b равно 0")
except ValueError:
print("Введите число")
Исключение ValueError
возникнет, если вы введете, например, строку вместо числа. Если необходимо выполнить одни и те же действия при разных типах исключений, то можно их объединить в одном блоке except
.
try:
a, b = int(input()), int(input())
print(a / b)
except (ZeroDivisionError, ValueError):
print("Ошибка в работе программы.")
Конструкция try/except
поддерживает возможность перехватывать все исключения, для этого можно не указывать тип:
try:
a, b = int(input()), int(input())
print(a / b)
except:
print("Ошибка в работе программы.")
Конструкция try/except
в Python имеет еще два опционных блока: finally
и else
. Блок finally
выполняется всегда, независимо от того, было исключение или нет. Снова может показаться, что это бесполезный блок, ведь если except
будет ловить все ошибки, то последующий код будет без проблем выполняться. Приведу пример, когда блок finally
действительно необходим:
import sys
try:
while True:
pass
except KeyboardInterrupt:
print('Ctrl + C')
sys.exit()
finally:
print("Выполнение чего-то важного")
print("Конец программы")
Программа будет закрыта только при помощи сочетания клавиш Ctrl + C
. Запустите пример и убедитесь что последний print()
будет пропущен. А что если перед закрытием программы при помощи сочетания клавиш Ctrl + C
необходимо сохранить пользовательскую информацию? Блок finally
в данном случае вас выручит.
Опционный блок else
в конструкции try/except
нужен, чтобы выполнить необходимые инструкции только в том случае, если исключения не вызывались. Далее пример:
try:
a, b = int(input()), int(input())
print(a / b)
except:
print("Ошибка в работе программы.")
else:
print("Конец программы")
Ключевое слово as в Python
Ключевое слово as
в контексте исключений может помочь узнать, какое именно исключение было поднято.
try:
a, b = int(input()), int(input())
print(a / b)
except Exception as e:
print(f"Исключение: {type(e)}")
print(f"Что случилось: {e}")
В этом примере мы используем f-строки и функцию type(). Если про них забыли, то вернитесь к этим урокам чтобы освежить в памяти. К ключевому слову as
мы еще вернемся, когда будем работать с файлами.
Ключевое слово raise в Python
Иногда необходимо сгенерировать исключение, можно использовать ключевое слово raise
:
try:
a, b = int(input()), int(input())
if (b == 0):
raise ZeroDivisionError
print(a / b)
except ZeroDivisionError:
print("Деление на ноль")
Или вы можете вызвать свое исключение в виде текстового сообщения:
try:
a, b = int(input()), int(input())
if (b == 0):
raise ValueError("Деление на ноль")
print(a / b)
except Exception as e:
print(e)
Утверждение assert в Python
Утверждение assert
в Python используется в отладочных целях, а именно, для проверки истинности утверждений. Если результат проверки будет ложным, то будет возбуждено исключение AssertionError
.
Инструкцию assert
рекомендуется использовать для проверки ситуаций, которые не должны происходить, то есть те, которые нельзя обработать.
Заключение
В процессе программирования ошибок не избежать. Ошибки могут появиться как из-за неправильного ввода данных пользователем, так и по многим другим причинам, включая невнимательность программиста.
В этом уроке мы научились обрабатывать ошибки в Python при помощи конструкций try/except
, try/except/else
и try/except/finally
. Узнали, как возбудить свою ошибку при помощи ключевого слова raise
. Кратко узнали о ключевом слове as
и утверждении assert
.
Перед обработкой исключений, оцените как проще и эффективней предупредить ошибку: использовать try/except
или обычную условную конструкцию if
. Далее подведем итоги раздела «Снова циклы и немного исключений» и начнем работать с файлами.
Тест
Похожие уроки Codebra
Подписывайся на наш Telegram-канал!
Новости, полезный материал,
программирование и ИБ
Подписывайся на наш Telegram-канал!
Новости, полезный материал,
программирование и ИБ