Наверное, вы уже неоднократно сталкивались с ошибками в коде, возникшими во время выполнения программы. Возникновение такой ошибки называется исключением, или, на английском языке — exception.
Существует множество видов исключений. Вспомним наш старый пример, где мы делили на ноль. Там мы получили исключение с названием ZeroDivisionError. В следующем примере приводится другое исключение — ValueError, возникающее, когда мы пытаемся передать строку символов в целочисленную переменную.>>> int(«not a number»)
1 2 3 4 | Traceback (most recent call last): File "<pyshell#1>", line 1, in <module> int("not a number") ValueError: invalid literal for int() with base 10: 'not a number' |
Тип исключения выводится в последней строке сообщения об ошибке.
Существует способ избежать прерывания работы программы в случае возникновения подобных ситуаций. Для этого существует пара операторов try/except:
1 2 3 4 | try: number = int(raw_input("Enter an integer: ")) except ValueError: print "Not an integer." |
Сначала код из блока try выполняется в обычном режиме. Если ошибок не возникает, то содержимое блока except выполнено не будет. Если же во время выполнения программы возникнет исключение типа ValueError, то программа сразу переключится на блок except и выполнит его содержимое. Программа не вылетит с ошибкой, так как мы «отловили» исключение.
Если возникнет другой тип исключения (не ValueError), то программа все равно прервет свое выполнение и выдаст нам сообщение об ошибке.
Простой except-блок может обрабатывать несколько типов исключений сразу. Их нужно перечислить через запятые и поместить в круглые скобки.
1 2 3 4 5 6 7 | from __future__ import division def divide(num1, num2): try: print num1 / num2 except (TypeError, ZeroDivisionError): print "encountered a problem" |
В этом примере написана функция divide, которая пытается поделить число num1 на num2. TypeError возникнет, если мы попытаемся поделить нечисловое значение, а ZeroDivisionError возникнет если в num2 мы передадим 0. Любое из этих исключение вызовет выполнение блока except и сообщит нам, что»encountered a problem». Далее программа продолжит выполнять код за пределами блока try/except.
Если возникает необходимость обрабатывать каждое исключение отдельно, то поступим следующим образом:
1 2 3 4 5 6 7 | try: number = int(raw_input("Enter an non-zero integer: ")) print "10 / {} = {}".format(number, 10.0/number) except ValueError: print "You did not enter an integer." except ZeroDivisionError: print "You cannot enter 0." |
Из примера следует, что в случае возникновения ошибки ValueError мы увидим сообщение «You did not enter an integer.», а в случае ZeroDivisionError сообщение — «You cannot enter 0.»
Мы можем использовать блок except без указания конкретного типа ошибки. Код в нем будет выполнен в случае возникновения любого исключения.
1 2 3 4 | try: # do lots of things except: print "The user must have screwed something up." |
Но, в соответствии с дзеном языка, так делать нежелательно. Легко поддаться соблазну и поместить плохо написанный кусок кода в блок try/except в надежде, что все будет работать хорошо, а на самом деле натолкнуться на множество проблем, которые можно было предвидеть. Грамотное применение обработки исключений сильно облегчает жизнь программиста.
Полный список типов встроенных исключений вы можете найти здесь https://docs.python.org/2/library/exceptions.html.