Исключения
Исключения возникают тогда, когда в программе возникает некоторая исключительная ситуация. Например, к чему приведёт попытка чтения несуществующего файла? Или если файл был случайно удалён, пока программа работала? Такие ситуации обрабатываются при помощи исключений.
Это касается и программ, содержащих недействительные команды. В этом случае Python поднимает руки и сообщает, что обнаружил ошибку.
Ошибки
Рассмотрим простой вызов функции print. Что, если мы ошибочно напишем print как Print? Обратите внимание на заглавную букву. В этом случае Python поднимает синтаксическую ошибку.
>>> Print('Привет, Мир!')
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
Print('Привет, Мир!')
NameError: name 'Print' is not defined
>>> print('Привет, Мир!')
Привет, Мир!Обратите внимание, что была поднята ошибка NameError, а также указано место, где была обнаружена ошибка. Так в данном случае действует обработчик ошибок.
Исключения
Попытаемся считать что-либо от пользователя. Нажмите Сtrl-D (или Ctrl+Z в Windows) и посмотрите, что произойдёт.
>>> s = input('Введите что-нибудь --> ')
Введите что-нибудь -->
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
s = input('Введите что-нибудь --> ')
EOFError: EOF when reading a linePython поднимает ошибку с именем EOFError, что означает, что он обнаружил символ конца файла (который вводится при помощи Ctrl-D) там, где не ожидал.
Обработка исключений
Обрабатывать исключения можно при помощи оператора try..except. При этом все обычные команды помещаются внутрь try-блока, а все обработчики исключений – в except-блок.
Пример: (сохраните как try_except.py)
try:
text = input('Введите что-нибудь --> ')
except EOFError:
print('Ну зачем вы сделали мне EOF?')
except KeyboardInterrupt:
print('Вы отменили операцию.')
else:
print('Вы ввели {0}'.format(text))Вывод:
$ python3 try_except.py
Введите что-нибудь --> # Нажмите ctrl-d
Ну зачем вы сделали мне EOF?
$ python3 try_except.py
Введите что-нибудь --> # Нажмите ctrl-c
Вы отменили операцию.
$ python3 try_except.py
Введите что-нибудь --> без ошибок
Вы ввели без ошибокКак это работает:
Здесь мы поместили все команды, которые могут вызвать исключения/ошибки, внутрь блока
try, а затем поместили обработчики соответствующих ошибок/исключений в блокexcept. Выражениеexceptможет обрабатывать как одиночную ошибку или исключение, так и список ошибок/исключений в скобках. Если не указано имя ошибки или исключения, обрабатываться будут все ошибки и исключения.
Помните, что для каждого выражения try должно быть хотя бы одно соответствующее выражение except. Иначе какой смысл был бы в блоке try?
Если ошибка или исключение не обработано, будет вызван обработчик Python по умолчанию, который останавливает выполнение программы и выводит на экран сообщение об ошибке. Выше мы уже видели это в действии.
Можно также добавить пункт else к соответствующему блоку try..except. Этот пункт будет выполнен тогда, когда исключений не возникает.
В следующем примере мы увидим, как можно получить объект исключения для дальнейшей работы с ним.
Вызов исключения
Исключение можно поднять при помощи оператора raise, передав ему имя ошибки/исключения, а также объект исключения, который нужно выбросить.
Вызываемая ошибка или исключение должна быть классом, который прямо или непрямо является производным от класса Exception.
Пример: (сохраните как raising.py)
class ShortInputException(Exception):
'''Пользовательский класс исключения.'''
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
try:
text = input('Введите что-нибудь --> ')
if len(text) < 3:
raise ShortInputException(len(text), 3)
# Здесь может происходить обычная работа
except EOFError:
print('Ну зачем вы сделали мне EOF?')
except ShortInputException as ex:
print('ShortInputException: Длина введённой строки -- {0}; \
ожидалось, как минимум, {1}'.format(ex.length, ex.atleast))
else:
print('Не было исключений.')Вывод:
$ python3 raising.py
Введите что-нибудь --> а
ShortInputException: Длина введённой строки -- 1; ожидалось, как минимум, 3
$ python3 raising.py
Введите что-нибудь --> абв
Не было исключений.Как это работает:
Здесь мы создаём наш собственный тип исключения. Этот новый тип исключения называется
ShortInputException. Он содержит два поля:length, хранящее длину введённого текста, иatleast, указывающее, какую минимальную длину текста ожидала программа.В пункте
exceptмы указываем класс ошибкиShortInputException, который будет сохранён как переменнаяex, содержащая соответствующий объект ошибки/исключения. Это аналогично параметрам и аргументам при вызове функции. Внутри этого пунктаexceptмы используем поляlengthиatleastобъекта исключения для вывода необходимых сообщений пользователю.
Try .. Finally
Представим, что в программе происходит чтение файла и необходимо убедиться, что объект файла был корректно закрыт и что не возникло никакого исключения. Этого можно достичь с применением блока finally.
Сохраните как finally.py:
import time
try:
f = open('poem.txt')
while True: # наш обычный способ читать файлы
line = f.readline()
if len(line) == 0:
break
print(line, end='')
time.sleep(2) # Пусть подождёт некоторое время
except KeyboardInterrupt:
print('!! Вы отменили чтение файла.')
finally:
f.close()
print('(Очистка: Закрытие файла)')Вывод:
$ python3 finally.py
Программировать весело
Если работа скучна,
Чтобы придать ей весёлый тон -
!! Вы отменили чтение файла.
(Очистка: Закрытие файла)Как это работает:
Здесь мы производим обычные операции чтения из файла, но в данном случае добавляем двухсекундный сон после вывода каждой строки при помощи функции
time.sleep, чтобы программа выполнялась медленно (ведь Python очень быстр от природы). Во время выполнения программы нажмитеctrl-c, чтобы прервать/отменить выполнение программы.Пронаблюдайте, как при этом выдаётся исключение
KeyboardInterrupt, и программа выходит. Однако, прежде чем программа выйдет, выполняется пунктfinally, и файловый объект будет всегда закрыт.
Оператор with
Типичной схемой является запрос некоторого ресурса в блоке try с последующим освобождением этого ресурса в блоке finally. Для того, чтобы сделать это более “чисто”, существует оператор with:
Сохраните как using_with.py:
with open("poem.txt") as f:
for line in f:
print(line, end='')Как это работает:
Вывод должен быть таким же, как и в предыдущем примере. Разница лишь в том, что здесь мы используем функцию
openс операторомwith– этим мы оставляем автоматическое закрытие файла под ответственностьwith open.За кулисами происходит следующее. Существует некий протокол, используемый оператором
with. Он считывает объект, возвращаемый операторомopen. Назовём его в данном случае “thefile”.Перед запуском блока кода, содержащегося в нём, оператор
withвсегда вызывает функциюthefile.__enter__, а также всегда вызываетthefile.__exit__после завершения выполнения этого блока кода.Так что код, который мы бы написали в блоке
finally, будет автоматически обработан методом__exit__. Это избавляет нас от необходимости повторно в явном виде указывать операторыtry..finally.Более обширное рассмотрение этой темы выходит за рамки настоящей книги, поэтому для более исчерпывающего объяснения см. PEP 343.
Last updated
Was this helpful?