- Часть I. Вводное руководство
- Глава 2. Использование интерпретатора
- 2.2. Интерпретатор и его среда
- 8.3. Обработка исключений
8.3. Обработка исключений
Вы можете писать программы, которые будут обрабатывать определенные исключения. Посмотрите на следующий пример, в котором пользователю будет выдаваться приглашение до тех пор, пока не будет введено целое число или выполнение не будет прервано (обычно Ctrl-C). Во втором случае генерируется исключение KeyboardInterrupt.
>>> while 1:
... try:
... x = int(raw_input("Введите, пожалуйста, целое число: "))
... except ValueError:
... print "Вы ошиблись. Попробуйте ещё раз..."
...
Инструкция try работает следующим образом.
1) Сначала выполняется ветвь try (инструкции, находящиеся между ключевыми словами try и except).
2) Если не возникает исключительной ситуации, ветвь except пропускается и выполнение инструкции try завершается.
3) Если во время выполнения ветви try генерируется исключение, оставшаяся часть ветви пропускается. Далее, если тип (класс) исключения соответствует указанному после ключевого слова except, выполняется ветвь except и выполнение инструкции try завершается.
4) Если исключение не соответствует указанному после ключевого слова except, то оно передается внешнему блоку try или, если обработчик не найден, исключение считается не пе рехваченным, выполнение прерывается и выводится сообщение об ошибке.
Инструкция try может иметь более одной ветви except, определяя обработчики для разных исключений. Выполняться будет (как максимум) только один из них. Обрабатываются только исключения, сгенерированные в соответствующей ветви try, но не в других обработчиках инструкции try. После ключевого слова except может быть указано несколько типов исключений в виде кортежа:
except (RuntimeError, TypeError, NameError):
pass
В последней ветви except тип исключения может быть опущен — в этом случае будут обрабатываться все исключения. Используйте такую запись с особой осторожностью — так Вы легко можете замаскировать реальные ошибки! Перехват всех исключений можно использовать для вывода сообщения об ошибке, а затем повторно сгенерировать его (позволяя обрабатывать исключение в другом месте):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError, exc:
print "Ошибка ввод/вывода", exc
except ValueError:
print "Не могу преобразовать данные к целому типу."
except:
print "Неожиданная ошибка:", sys.exc_info()[0]
raise # Повторно генерирует последнее перехваченное исключение
После всех ветвей except, инструкция try может содержать ветвь else, которая будет выполняться в случае, если во время выполнения ветви try исключения не генерируются. Например:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'Не могу открыть', arg
else:
print arg, 'содержит', len(f.readlines()), \
'строк'
f.close()
Обычно лучше использовать ветвь else, чем добавлять код в основную ветвь инструкции try, так как это позволяет избежать обработки исключений, сгенерированных кодом, который Вы вовсе не собирались защищать.
Исключение может иметь ассоциированное с ним значение — аргумент, переданный классу исключения при инициализации. Наличие и тип аргумента зависит от типа исключения. Ассоциированное значение используется при получении для исключения строкового значения. Чтобы получить значение исключения, в ветви except после класса исключения (или кортежа классов) укажите переменную:
>>> try:
... spam()
... except NameError, x:
... print 'Имя', x, 'не определено'
...
Имя name 'spam' is not defined не определено
Если исключение не обрабатывается, значение исключения выводится в сообщении об ошибке после имени класса исключения.
Обработчик перехватывает не только исключения, сгенерированные непосредственно в блоке try, но и в вызываемых из него функциях. Например:
>>> def this_fails():
... x = 1/0
...
>>> try:
... this_fails()
... except ZeroDivisionError, exc:
... print 'Ошибка времени выполнения:', exc
...
Ошибка времени выполнения: integer division or modulo by zero