Конструкция try - except для обработки исключений
Допустим, нам нужно написать функцию, которая возвращает частное от деления двух чисел; и ноль, если деление не удалось.
Кажется легко, верно? Давайте напишем код:
def division(x, y):
return x / y
И вызовем его
>>> print(division(1, 0))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in division
ZeroDivisionError: division by zero
Ошибка деления на ноль. Или как говорят, возникло исключение. Исключения можно избежать, если, например, до операции деления выполнить проверку на 0:
def division(x, y):
if y == 0:
return 0
return x / y
А тогда ещё пример:
>>> print(division(1.5, 7 ** 512))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in division
OverflowError: int too large to convert to float
Если первый аргумент - число с плавающей точкой, а второй - большое целое число, то Python, пытаясь преобразовать его в число с плавающей точкой, терпит неудачу.
Можно, конечно, добавить ещё проверок. Но есть более простой способ, а именно обработать исключение с помощью конструкции try - except:
def division(x, y):
if y == 0:
return 0
try:
answer = x / y
except OverflowError:
answer = 0
return answer
Программа пытается выполнить код в блоке try. Если получается, то далее выполнится то, что после блока. В нашей функции это возврат переменной answer.
Если не получается, то выполнение внутри блока try прерывается, а затем интерпретатор смотрит, что за исключение произошло. Если оно (либо его родитель) есть в одном из списков except, то выполнится блок except. Иначе возникнет исключение, то самое, которое было в блоке try.
Можно убрать проверку на 0, написав вместо неё обработку исключения в отдельном блоке except (и таких блоков может быть сколько угодно):
def division(x, y):
try:
answer = x / y
except OverflowError:
answer = 0
except ZeroDivisionError:
answer = 0
return answer
записав имена исключения через запятую (только потому, что обработка обоих из них у нас одинакова):
def division(x, y):
try:
answer = x / y
except (OverflowError, ZeroDivisionError):
answer = 0
return answer
или, поскольку OverflowError и ZeroDivisionError это подвид ArithmeticError, можно перехватить только его:
def division(x, y):
try:
answer = x / y
except ArithmeticError:
answer = 0
return answer
try - except - else
Инструкция else в блоке try - except выполнится только, если при выполнении блока try не было исключения:
def division(x, y):
try:
answer = x / y
except ArithmeticError:
answer = 0
else:
print("Деление было выполнено штатно")
return answer
finally
Инструкции в блоке finally блока try - except выполнятся при любом исходе блока try. Даже если возникнет не отловленное исключение, перед выдачей ошибки выполнится блок finally:
def division(x, y):
try:
answer = x / y
except OverflowError:
answer = 0
else:
print("Деление было выполнено штатно")
finally:
print("Заходи в наш телеграм-канал (ссылка внизу)")
return answer
print(division(2, 1))
print()
print(division(1.5, 7 ** 512))
print()
print(division(1, 0))
И вывод данной программы:
Деление было выполнено штатно
Заходи в наш телеграм-канал (ссылка внизу)
2.0
Заходи в наш телеграм-канал (ссылка внизу)
0
Заходи в наш телеграм-канал (ссылка внизу)
Traceback (most recent call last):
File "C:\Users\Дмитрий\PycharmProjects\pyplanet\functional.py", line 17, in <module>
print(division(1, 0))
^^^^^^^^^^^^^^
File "C:\Users\Дмитрий\PycharmProjects\pyplanet\functional.py", line 3, in division
answer = x / y
~~^~~
ZeroDivisionError: division by zero
Обычно инструкция finally нужна для того, чтобы корректно освободить ресурсы: открытые файлы, дополнительные процессы или окна и т.д.
Полный список встроенных исключений можно узнать в нашем справочнике. Полезно знать, какие исключения могут возникать в каких ситуациях.