-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexceptions.py
More file actions
182 lines (159 loc) · 10.4 KB
/
exceptions.py
File metadata and controls
182 lines (159 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
# Copyright (c) 2015 Artur Eganyan
#
# This work is provided "AS IS", WITHOUT ANY WARRANTY, express or implied.
#-------------------------------------------------------------------------------
# Исключение - это особая ситуация (обычно - ошибка), прерывающая нормальное
# выполнение программы. Исключение генерируется интерпретатором или вручную
# инструкцией raise, прерывает выполнение текущего блока кода и передается в
# первый подходящий блок обработки (except). Если такого блока нет, программа
# завершается и выводит стек вызовов (traceback), которые привели к
# исключению (а если произошло исключение SystemExit - не выводит).
#
# Исключение представляется экземпляром класса, наследующего от Exception.
# Этот экземпляр создается при генерации исключения и передается в блок except.
# Исключение генерируется инструкцией raise:
#
# raise MyException("Error message")
# raise MyException, "Error message" # То же самое
#
# raise без параметров генерирует текущее исключение заново - это нужно, если
# блок except, перехвативший исключение, не может его обработать и хочет
# передать его вышестоящим блокам.
#
# Блок, перехватывающий возникающие исключения, выглядит так:
#
# try:
# <код, в котором может возникнуть исключение>
#
# except <класс исключения> [as <переменная>]:
# <код, обрабатывающий исключение>
#
# else:
# <код, выполняющийся при нормальном завершении try>
#
# finally:
# <код, выполняющийся всегда>
#
# Блоков except может быть много. <класс исключения> может содержать несколько
# классов, перечисленных в круглых скобках (<класс1>, ..., <классN>). Может
# быть блок except вообще без классов, перехватывающий любые исключения -
# тогда он должен стоять после всех других except. Перед тем, как будет
# выполнен except, информация об исключении сохраняется в модуле sys и может
# быть получена вызовом sys.exc_info().
#
# Блок else выполняется, если try был полностью выполнен, без исключений и
# без выхода инструкцией return / break / continue (break и continue могут
# быть, когда try находится внутри цикла).
#
# Блок finally выполняется всегда, последним. Если к моменту выполнения finally
# есть неперехваченное исключение, оно запоминается, и затем выполняется
# finally, у которого нет доступа к этому исключению. После завершения finally
# сохраненное исключение генерируется снова. Неперехваченное исключение может
# произойти в try, except или else.
#
# Замечание: Если в самом finally возникло исключение или была выполнена
# инструкция return / break, предыдущее неперехваченное исключение будет
# потеряно. Инструкция continue в finally на данный момент запрещена
# "из-за особенностей реализации".
try:
x = 1/0
except Exception as e:
print e # integer division or modulo by zero
try:
x = "1" + 1 # Тут произойдет TypeError
except ArithmeticError: # Этот блок не будет выбран
print "?"
except (TypeError, NameError) as e: # Этот блок будет выбран, потому что есть TypeError
print e # cannot concatenate 'str' and 'int' objects
finally:
print "finally" # Будет выполнено в самом конце
for i in range(5):
try:
print "try"
if i > 0:
continue
except: # Не будет выполнен (нет исключений)
print "except"
else: # Не выполнится при i > 0, потому что try будет
print "else" # прерываться инструкцией continue
finally: # Выполнится в самом конце
print "finally"
#continue # Приведет к SyntaxError, потому что continue не
# поддерживается в блоке finally
import sys
try:
try:
raise Exception("A")
except:
raise Exception("B")
finally:
print sys.exc_info() # Выведет информацию об исключении A. Неперехваченное
# исключение B на данный момент сохранено, но недоступно.
print "finally" # Блок finally выполнится после except
except:
print sys.exc_info() # Выведет информацию об исключении B
# Использование своего исключения (конструктор __init__ здесь можно
# было не объявлять - тогда был бы вызван конструктор Exception)
class MyException(Exception):
def __init__(self, message):
Exception.__init__(self, message)
try:
raise MyException("Some exception")
except MyException as e:
print e
# В python 2.x исключение может не наследовать от Exception
class StrangeException:
pass
try:
raise StrangeException
except StrangeException:
print u"Странное исключение поймано"
# Замечание: В except можно указывать не только класс исключения, но и
# выражение, возвращающее класс (но вряд ли это часто требуется). Если в таком
# выражении возникнет исключение, оно будет передано вне текущего try.
def f(i):
print "f(", i, ")"
if i == 0:
return Exception
elif i == 1:
return TypeError
else:
raise Exception("i = 2")
try:
for i in range(3):
try:
raise Exception("test")
except f(i) as e: # При поиске подходящего except каждый раз будет
# вызываться f(), которая возвращает класс исключения
print e # Выполнится при i = 0
except:
print u"f(i) вернула TypeError" # Выполнится при i = 1
except:
print u"f(i) сгенерировала исключение" # Выполнится при i = 2
# Замечание: Любой из блоков except / else / finally может отсутствовать.
# Но тесты показывают, что else может быть только при наличии except, и что
# try не может быть "без ничего" - с ним должен быть except или finally.
#
# Замечание: В блоке except <класс исключения> может быть любым выражением.
# При поиске подходящего except интерпретатор вычисляет выражения в каждом
# блоке, и выбирает тот, у которого результат выражения совместим с
# возникшим исключением. А именно, у которого результат равен _классу_
# исключения, его базовому классу или кортежу, содержащему класс / базовый
# класс. И затем ссылка на исключение записывается в <переменную>. Выражение,
# возвращающее класс, наверное используется редко. Но если в ходе его
# вычисления возникнет исключение, оно будет передано за пределы
# текущего блока try/except, а предыдущее исключение будет потеряно.
#
# Замечание: В python 2.x класс исключения не обязательно должен наследовать
# от Exception. Правда, в документации к классу Exception написано "All
# user-defined exceptions should also be derived from this class", но в
# Tutorial/Classes приведен пример, где используются ненаследующие классы.
# В документации к python 3.x в этом же примере классы наследуют от Exception.
#
# Замечание: В python 2.x в except можно писать "<класс> as <переменная>" или
# "<класс>, <переменная>". Из-за этого, если нужно указать несколько классов,
# их надо записывать в скобках: (<класс1>, ..., <классN>) as <переменная>. В
# python 3.x вроде как запретили писать "<класс>, <переменная>", чтобы
# случайно не перечисляли "<класс1>, <класс2>, ...".