Исключительные ситуации.
Возникают либо при ошибке работы пользователя, либо при ошибке в логике программы. Исключительных ситуаций существует много: деление на нуль, использование несуществующего модуля или переменной, многие стандартные функции также генерируют исключения в случае неверной работы. Приведём примеры таких ситуаций:
>>> 10 * (1/0) Traceback (most recent call last):
File "<stdin>", line 1, in ?
ZeroDivisionError: integer division or modulo #Деление на нуль
>>> 4 + spam*3 Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: spam
#Нет такого имени переменной >>> '2' + 2 Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: illegal argument type for built-in operation#Смешение разных типов
Конечно, всё было бы отлично, если пользователя удовлетворяли подобные сообщения, я лично в этом сильно сомневаюсь. Кроме этого, исключения могут генерировать ся в любой момент программы, что может вызвать потерю данных. По всем этим причинам желательно предусматривать возможность перехватывать исключения. Для этого используется блок try, который исполняет операторы внутри блока, но если возбуждается исключение, то оператор try ищет обработчик исключения(прерывая исполнение блока кода внутри try), обозначаемый except имя_исключения . Если обработчик не найден, то он ищется в других блоках try, если он не найден, то возникает непредвиденное(unhandled) исключение, которое отображается, как в предыдущем примере. Блок try выполняется до конца при отсутствии исключительных ситуаций, блоки except при этом пропускаются:
>>> while 1: ... try: ... x = int(raw_input("Введите число ")) #Здесь может возникнуть исключение ... break #Если всё правильно, то выходим из бесконечного while
... except ValueError: #А вот здесь обрабатывается исключение неверного формата числа ... print ''Ой-ой. Неправильное число. Попробуйте снова..."
Оператор except может принимать несколько имён исключений, оформленных в скобках через запятую:
... except (RuntimeError, TypeError, NameError): ... pass
Обработчики исключений могут принимать некоторые параметры, причём их число и последовательность специфична для каждого типа исключения. Также есть возможность создавать обработчик исключений по умолчанию, который обрабатывает все исключения, для которых не был определён конкретный обработчик:
import string, sys
try: f = open('myfile.txt') s = f.readline() i = int(string.strip(s)) except IOError, (errno, strerror): print "I/O ошибка(%s): %s" % (errno, strerror) except ValueError: print "Не могу преобразовать это в целое." except: print "Неожиданная ошибка:", sys.exc_info()[0] #Имя последнего исключения raise #Возбуждение данного исключения ещё раз(см. далее)
В блоке 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()
Обработчики исключений способны обрабатывать исключения не только непосредственно в блоке try, но и в функциях, вызываемых из этого блока, например:
>>> def this_fails(): ... x = 1/0 ... >>> try: ... this_fails() #Функция, вызывающая исключительную ситуацию ... except ZeroDivisionError, detail: ... print 'Возбуждено исключение:', detail ... Возбуждено исключение: integer division or modulo