Глава 10 • Файлы и исключения
Ошибка, упоминаемая в трассировке
—
ZeroDivisionError
, — является объектом
исключения. Такие объекты создаются в том случае, если Python не может выпол-
нить ваши распоряжения. Обычно в таких случаях Python прерывает выполнение
программы и сообщает тип обнаруженного исключения. Эта информация может
использоваться в программе; по сути вы сообщаете Python, как следует поступить
при возникновении исключения данного типа. В таком случае ваша программа
будет подготовлена к его появлению.
Блоки try-except
Если вы предполагаете, что в программе может произойти ошибка, напишите блок
try
-
except
для обработки возникающего исключения. Такой блок приказывает
Python выполнить некоторый код, а также сообщает, что нужно делать, если при
его выполнении произойдет исключение конкретного типа.
Вот как выглядит блок
try
-
except
для обработки исключений
ZeroDivisionError
:
try:
print(5/0)
except ZeroDivisionError:
print("You can't divide by zero!")
Команда
print(5/0)
, порождающая ошибку, находится в блоке
try
. Если код в бло-
ке
try
выполнен успешно, то Python пропускает блок
except
. Если код в блоке
try
порождает ошибку, то Python ищет блок
except
с соответствующей ошибкой
и выпускает код в этом блоке.
В этом примере код блока
try
порождает ошибку
ZeroDivisionError
, поэтому
Python ищет блок
except
с описанием того, как следует действовать в такой ситу-
ации. При выполнении кода этого блока пользователь видит понятное сообщение
об ошибке вместо данных трассировки:
You can't divide by zero!
Если бы за кодом
try
-
except
следовал другой код, то выполнение программы
продолжилось, потому что мы объяснили Python, как обрабатывать эту ошибку.
В следующем примере обработка ошибки позволяет программе продолжить вы-
полнение.
Использование исключений для предотвращения аварийного
завершения программы
Правильная обработка ошибок особенно важна в том случае, если программа
должна продолжить работу после возникновения ошибки. Такая ситуация часто
встречается в программах, запрашивающих данные у пользователя. Если програм-
ма правильно среагировала на некорректный ввод, она может запросить новые
данные после сбоя.
Создадим простой калькулятор, который выполняет только операцию деления:
Исключения
197
division.py
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
if second_number == 'q':
break
answer = int(first_number) / int(second_number)
print(answer)
Программа запрашивает у пользователя первое число
first_number
, а затем,
если пользователь не ввел
q
для завершения работы, запрашивает второе число
second_number
. Далее одно число делится на другое для получения результата
answer
. Программа никак не обрабатывает ошибки, так что попытка деления на
ноль приводит к ее аварийному завершению:
Give me two numbers, and I'll divide them.
Enter 'q' to quit.
First number: 5
Second number: 0
Traceback (most recent call last):
File "division.py", line 9, in
answer = int(first_number) / int(second_number)
ZeroDivisionError: division by zero
Конечно, аварийное завершение — это плохо, но еще хуже, если пользователь
увидит данные трассировки. Неопытного пользователя они собьют с толку, а при
сознательной попытке взлома злоумышленник сможет получить из них больше
информации, чем вам хотелось бы. Например, он узнает имя файла программы
и увидит некорректно работающую часть кода. На основании этой информации
опытный хакер иногда может определить, какие атаки следует применять против
вашего кода.
Блок else
Для повышения устойчивости программы к ошибкам можно заключить строку,
выдающую ошибки, в блок
try
-
except
. Ошибка происходит в строке, выполняющей
деление; следовательно, именно эту строку следует заключить в блок
try
-
except
.
Данный пример также включает блок
else
. Любой код, зависящий от успешного
выполнения блока
try
, размещается в блоке
else
:
print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
198
Достарыңызбен бөлісу: |