1
00:00:05,540 --> 00:00:07,280
alright so let's have a look in more

2
00:00:07,280 --> 00:00:09,200
detail now the stack trace has been

3
00:00:09,200 --> 00:00:11,390
printed out here now because of the way

4
00:00:11,390 --> 00:00:13,790
that the stack trace is generated it may

5
00:00:13,790 --> 00:00:15,590
be interspersed with the program's

6
00:00:15,590 --> 00:00:18,040
output if i run the program a few times

7
00:00:18,040 --> 00:00:20,810
you can probably see or you will see we

8
00:00:20,810 --> 00:00:23,930
don't always get the exact same contents

9
00:00:23,930 --> 00:00:25,720
well technically the content will be

10
00:00:25,720 --> 00:00:27,770
identical each time but the stack trace

11
00:00:27,770 --> 00:00:30,350
and the output can get mixed up and when

12
00:00:30,350 --> 00:00:32,180
it is mixed up we can't rely on what's

13
00:00:32,180 --> 00:00:34,700
been printed first we can say every time

14
00:00:34,700 --> 00:00:36,890
is that 4 ducks fly before we get an

15
00:00:36,890 --> 00:00:38,990
error to show you what I mean lets run

16
00:00:38,990 --> 00:00:41,420
this a few times so you can see that

17
00:00:41,420 --> 00:00:43,160
the stack trace is different there

18
00:00:43,160 --> 00:00:45,700
we've got dispersed in a different

19
00:00:45,700 --> 00:00:47,930
position than it was previously run it

20
00:00:47,930 --> 00:00:49,270
again we three at the top

21
00:00:49,270 --> 00:00:53,840
three lines of output and again we're

22
00:00:53,840 --> 00:00:55,000
getting different results pretty much

23
00:00:55,000 --> 00:00:57,730
every time we run it so we can't rely on

24
00:00:57,730 --> 00:00:59,570
what's been printed first all we can really

25
00:00:59,570 --> 00:01:01,820
say every time is that the four ducks

26
00:01:01,820 --> 00:01:04,660
fly before we get an error and that's

27
00:01:04,660 --> 00:01:06,890
true even if the trace starts to print

28
00:01:06,890 --> 00:01:09,020
before we see the fourth duck take to

29
00:01:09,020 --> 00:01:11,600
the air so reading from the bottom first

30
00:01:11,600 --> 00:01:13,820
and ignoring any text that doesn't

31
00:01:13,820 --> 00:01:15,530
appear mostly in red

32
00:01:15,530 --> 00:01:18,110
we've got an attribute error because the

33
00:01:18,110 --> 00:01:20,180
penguin has no attribute called fly

34
00:01:20,180 --> 00:01:22,490
right here down the bottom up until that

35
00:01:22,490 --> 00:01:25,820
the error as you can see here occurred on

36
00:01:25,820 --> 00:01:29,330
line 55 the migrate method and that's

37
00:01:29,330 --> 00:01:32,080
when it tried to called duck.fly so

38
00:01:32,080 --> 00:01:34,250
that's useful because it tells us where

39
00:01:34,250 --> 00:01:35,440
the error happened

40
00:01:35,440 --> 00:01:37,790
however we know there's not a problem

41
00:01:37,790 --> 00:01:39,400
with that particular line of code

42
00:01:39,400 --> 00:01:41,650
because we've seen 4 ducks already

43
00:01:41,650 --> 00:01:42,710
start flying

44
00:01:42,710 --> 00:01:44,510
so this is where the stack trace is

45
00:01:44,510 --> 00:01:47,180
useful now we've got code that works as

46
00:01:47,180 --> 00:01:49,760
long as its operating on the correct type

47
00:01:49,760 --> 00:01:51,680
of object to find out what's really

48
00:01:51,680 --> 00:01:54,190
caused the error we have to keep reading

49
00:01:54,190 --> 00:01:57,350
up the call stack so next we can see the

50
00:01:57,350 --> 00:02:00,290
migrate method was called on line 22

51
00:02:00,290 --> 00:02:02,390
duck.migrate as you can see here

52
00:02:02,390 --> 00:02:06,740
line 22 and in module and that means the

53
00:02:06,740 --> 00:02:09,250
main program when it called the flock .

54
00:02:09,250 --> 00:02:12,530
migrate method now sometimes that's all

55
00:02:12,530 --> 00:02:13,490
you need

56
00:02:13,490 --> 00:02:15,980
so if migrate accepted arguments that

57
00:02:15,980 --> 00:02:17,390
it would probably indicate a problem

58
00:02:17,390 --> 00:02:18,530
with one of the parameters

59
00:02:18,530 --> 00:02:21,290
but here though it's not quite

60
00:02:21,290 --> 00:02:23,730
that simple because we set up the flock

61
00:02:23,730 --> 00:02:26,570
earlier in the code but there are now

62
00:02:26,570 --> 00:02:27,900
enough clues to let us know that

63
00:02:27,900 --> 00:02:31,310
somehow the flocks got a penguin it now

64
00:02:31,310 --> 00:02:33,060
the important thing is that the cause

65
00:02:33,060 --> 00:02:35,370
of the error in this case isn't in ducks

66
00:02:35,370 --> 00:02:38,090
.py it's in a migration .py

67
00:02:38,090 --> 00:02:40,620
module now we've only got two modules here

68
00:02:40,620 --> 00:02:43,280
but we could have a coordinator program

69
00:02:43,280 --> 00:02:45,530
that calls another program to select

70
00:02:45,530 --> 00:02:47,760
different species of ducks that in turn

71
00:02:47,760 --> 00:02:50,370
calls our migrate module that uses

72
00:02:50,370 --> 00:02:53,030
the classes from ducks.py and

73
00:02:53,030 --> 00:02:55,310
things can get quite complex but with a

74
00:02:55,310 --> 00:02:57,120
stack trace like this it's much easier

75
00:02:57,120 --> 00:02:59,810
to find the root cause of errors and

76
00:02:59,810 --> 00:03:02,540
crashes alright so let's go see what

77
00:03:02,540 --> 00:03:05,370
we can do about this exception now in

78
00:03:05,370 --> 00:03:06,870
fact we've already done the first thing

79
00:03:06,870 --> 00:03:09,780
we could do we have done nothing so we

80
00:03:09,780 --> 00:03:11,810
didn't handle the exception in the

81
00:03:11,810 --> 00:03:13,820
migrate method so the exception

82
00:03:13,820 --> 00:03:16,950
propagated up the call stack to wherever

83
00:03:16,950 --> 00:03:19,430
called migrate and that was our main

84
00:03:19,430 --> 00:03:21,840
program and because that didn't handle

85
00:03:21,840 --> 00:03:22,790
the exception

86
00:03:22,790 --> 00:03:25,010
it got propagated up the python run time

87
00:03:25,010 --> 00:03:28,130
the Python runtime prints out this useful

88
00:03:28,130 --> 00:03:29,970
stacked trace and then terminates the

89
00:03:29,970 --> 00:03:33,200
program so if an exception isn't handled

90
00:03:33,200 --> 00:03:35,150
it will get passed up the call stack

91
00:03:35,150 --> 00:03:38,120
until either something handles it or it

92
00:03:38,120 --> 00:03:40,760
reaches the python runtime now having

93
00:03:40,760 --> 00:03:42,620
a program crashed like this isn't good

94
00:03:42,620 --> 00:03:44,570
but that doesn't mean that migrate

95
00:03:44,570 --> 00:03:46,700
method should handle the error it's so

96
00:03:46,700 --> 00:03:48,650
often better to leave errors for

97
00:03:48,650 --> 00:03:50,190
something further up the call chain to

98
00:03:50,190 --> 00:03:53,150
deal with so that's one option now is

99
00:03:53,150 --> 00:03:54,780
there anything useful that the migrate

100
00:03:54,780 --> 00:03:57,120
method could do in this case if

101
00:03:57,120 --> 00:03:59,340
there is we should actually do it but if

102
00:03:59,340 --> 00:04:01,070
there isn't then we should let the

103
00:04:01,070 --> 00:04:03,470
exception propagate to allow code

104
00:04:03,470 --> 00:04:05,120
that's in a better position to deal with

105
00:04:05,120 --> 00:04:08,030
the situation handle it now I don't know

106
00:04:08,030 --> 00:04:09,650
much about ducks and i'm pretty sure

107
00:04:09,650 --> 00:04:11,010
that once you've caused the flock of

108
00:04:11,010 --> 00:04:12,720
ducks to take flight

109
00:04:12,720 --> 00:04:14,060
there's no way to get them back on the

110
00:04:14,060 --> 00:04:17,630
ground now humane way that is but we can

111
00:04:17,630 --> 00:04:19,070
make sure that all the ducks that are

112
00:04:19,070 --> 00:04:22,350
capable of flying managed to migrate so

113
00:04:22,350 --> 00:04:23,340
to do that I'm going to start by

114
00:04:23,340 --> 00:04:25,880
catching the exception in the migrate

115
00:04:25,880 --> 00:04:30,300
method let's have a look at doing that

116
00:04:30,300 --> 00:04:32,310
i'm looking at our migrate method here

117
00:04:32,310 --> 00:04:36,650
so after the four we're going to....

118
00:04:36,650 --> 00:04:41,870
...

119
00:04:41,870 --> 00:04:52,830
...

120
00:04:52,830 --> 00:04:57,470
so this time you can see that all seven

121
00:04:57,470 --> 00:05:00,060
ducks manage to take off poor Percy is left

122
00:05:00,060 --> 00:05:02,150
on the ground but at least the rest of

123
00:05:02,150 --> 00:05:05,810
the flock are away but unfortunately the

124
00:05:05,810 --> 00:05:08,340
main programs now and none the wiser as

125
00:05:08,340 --> 00:05:09,900
far as our migration program is

126
00:05:09,900 --> 00:05:12,150
concerned we've got eight birds in the

127
00:05:12,150 --> 00:05:14,630
air so we didn't take any action in the

128
00:05:14,630 --> 00:05:16,850
exception handler so the exception was

129
00:05:16,850 --> 00:05:19,710
effectively just ignored so what we can

130
00:05:19,710 --> 00:05:24,810
do now that all the ducks safely flying

131
00:05:24,810 --> 00:05:27,470
is to raise the error that we've got

132
00:05:27,470 --> 00:05:30,240
when Percy attempted to fly now if we

133
00:05:30,240 --> 00:05:32,690
attempt to do that within the for loop the

134
00:05:32,690 --> 00:05:34,970
loop will terminate when we raise an

135
00:05:34,970 --> 00:05:37,530
exception so raising it in the exception

136
00:05:37,530 --> 00:05:39,530
handler will leave us no better off than

137
00:05:39,530 --> 00:05:42,410
before and to show you what i mean i'm

138
00:05:42,410 --> 00:05:45,210
going to change this Pass will print a

139
00:05:45,210 --> 00:05:51,300
message here one duck down they're and

140
00:05:51,300 --> 00:05:56,840
put raise run that again we're back to

141
00:05:56,840 --> 00:05:58,370
the same scenario where we were before

142
00:05:58,370 --> 00:06:00,560
or be that we've got an extra message

143
00:06:00,560 --> 00:06:02,600
here informing us that the percy

144
00:06:02,600 --> 00:06:05,000
didn't make it but importantly with now

145
00:06:05,000 --> 00:06:06,740
unfortunately only got four ducks in

146
00:06:06,740 --> 00:06:09,930
flight now you can log the values of

147
00:06:09,930 --> 00:06:12,120
local variables for example before

148
00:06:12,120 --> 00:06:14,520
raising the exception again some of the

149
00:06:14,520 --> 00:06:19,100
words are here and let the caller

150
00:06:19,100 --> 00:06:21,960
deal with it so to raise the exception

151
00:06:21,960 --> 00:06:24,330
that you just caught you just used the

152
00:06:24,330 --> 00:06:26,970
raise statement that has been typed in and

153
00:06:26,970 --> 00:06:29,810
actually preserves the stack trace so

154
00:06:29,810 --> 00:06:31,310
that all the useful information is still

155
00:06:31,310 --> 00:06:33,560
available for debugging and again if you

156
00:06:33,560 --> 00:06:35,300
run that again you can see that's the

157
00:06:35,300 --> 00:06:38,240
case so we still got our information

158
00:06:38,240 --> 00:06:40,190
and pir stack trace which we can see

159
00:06:40,190 --> 00:06:42,410
propagating up the call stack much as

160
00:06:42,410 --> 00:06:43,620
the case was before

161
00:06:43,620 --> 00:06:46,650
so basically all the useful information

162
00:06:46,650 --> 00:06:49,800
still available for debugging npw as O have

163
00:06:49,800 --> 00:06:51,900
said many times before everything in

164
00:06:51,900 --> 00:06:54,350
python is an object exceptions are no

165
00:06:54,350 --> 00:06:55,590
exception

166
00:06:55,590 --> 00:06:57,300
so we can obtain a reference to the

167
00:06:57,300 --> 00:07:00,630
exception that's just been raised and we

168
00:07:00,630 --> 00:07:02,340
do that with a slightly different form

169
00:07:02,340 --> 00:07:06,500
of the except Clause sp come back to

170
00:07:06,500 --> 00:07:09,180
our ducks.py to our migrated method

171
00:07:09,180 --> 00:07:11,690
and we do instead of typing accept

172
00:07:11,690 --> 00:07:14,820
attribute error at the end of that we do

173
00:07:14,820 --> 00:07:18,720
....so when used like this a

174
00:07:18,720 --> 00:07:20,520
reference to the exception is stored in

175
00:07:20,520 --> 00:07:22,940
a variable for us to do something with

176
00:07:22,940 --> 00:07:25,560
now one useful thing we could do is

177
00:07:25,560 --> 00:07:27,780
store the exception then raise it once

178
00:07:27,780 --> 00:07:30,000
all the Ducks are off the ground so to

179
00:07:30,000 --> 00:07:31,380
show you what I mean will delete the

180
00:07:31,380 --> 00:07:35,430
raise line which always commented out and

181
00:07:35,430 --> 00:07:40,880
we'll put..

182
00:07:40,880 --> 00:07:43,770
...

183
00:07:43,770 --> 00:07:51,960
...

184
00:07:51,960 --> 00:07:53,660
you can see we've got problem here local variable problem

185
00:07:53,660 --> 00:07:55,980
might be referenced before assignment so

186
00:07:55,980 --> 00:07:58,740
to fix that we should really assign

187
00:07:58,740 --> 00:08:00,900
value to this outside of the for loop so

188
00:08:00,900 --> 00:08:03,120
problem equals and we'll start with none

189
00:08:03,120 --> 00:08:05,340
that then remove that error

190
00:08:05,340 --> 00:08:07,530
so let's now run this to see what

191
00:08:07,530 --> 00:08:08,460
happens

192
00:08:08,460 --> 00:08:12,410
you can see this time we've actually got

193
00:08:12,410 --> 00:08:14,810
all seven ducks in the air one duck down

194
00:08:14,810 --> 00:08:16,850
for penguins didn't work and then we've

195
00:08:16,850 --> 00:08:19,190
got the error at the end so in other

196
00:08:19,190 --> 00:08:21,690
words that the seven ducks that can fly

197
00:08:21,690 --> 00:08:24,090
do so and our migration programs

198
00:08:24,090 --> 00:08:26,060
notified of the problem once they are all

199
00:08:26,060 --> 00:08:28,710
of the ground now you probably won't do

200
00:08:28,710 --> 00:08:31,710
that very often but it can be useful and

201
00:08:31,710 --> 00:08:33,659
it also shows another way to use raise

202
00:08:33,659 --> 00:08:36,299
which is to specify the exception that

203
00:08:36,299 --> 00:08:39,600
you want to raise so looking at the stack

204
00:08:39,600 --> 00:08:41,730
trace now we still got all the useful

205
00:08:41,730 --> 00:08:44,220
information that we had before the

206
00:08:44,220 --> 00:08:47,850
original problem was on line 57 ducks.py

207
00:08:47,850 --> 00:08:49,860
i can click that link to have a look

208
00:08:49,860 --> 00:08:50,490
at it

209
00:08:50,490 --> 00:08:53,100
that's the duck .fly called their we got

210
00:08:53,100 --> 00:08:54,480
another entry this time and clicking

211
00:08:54,480 --> 00:08:55,670
that takes us to the line where the

212
00:08:55,670 --> 00:08:57,150
exception was raised

213
00:08:57,150 --> 00:09:00,240
this one here in line 63 and just move

214
00:09:00,240 --> 00:09:03,390
this down a little bit line 63 is we've

215
00:09:03,390 --> 00:09:06,150
raised the exception clicking on the

216
00:09:06,150 --> 00:09:08,990
first link takes us to well the actual

217
00:09:08,990 --> 00:09:11,550
line where we call the migrate method

218
00:09:11,550 --> 00:09:15,090
so the stack trace is slightly different

219
00:09:15,090 --> 00:09:16,890
but it still contains all the

220
00:09:16,890 --> 00:09:20,340
information you had before so

221
00:09:20,340 --> 00:09:22,350
let's end the video here in the next

222
00:09:22,350 --> 00:09:24,920
video we're going to talk about creating

223
00:09:24,920 --> 00:09:26,850
your own exceptions see you in the next

224
00:09:26,850 --> 00:09:32,210
video

