1
00:00:01,310 --> 00:00:02,740
Hi, guys, and welcome back.

2
00:00:02,740 --> 00:00:05,973
In this video, we're going to learn about errors in Python.

3
00:00:07,020 --> 00:00:10,060
What we've got here is a simple divide function,

4
00:00:10,060 --> 00:00:11,700
that takes in two parameters.

5
00:00:11,700 --> 00:00:13,100
If the divisor is equal to zero,

6
00:00:13,100 --> 00:00:15,740
it prints that it cannot be zero and then returns.

7
00:00:15,740 --> 00:00:19,480
Otherwise, it'll return the dividend divided by the divisor.

8
00:00:19,480 --> 00:00:22,780
If we run this code, you should see that you get a print,

9
00:00:22,780 --> 00:00:25,080
Divisor cannot be zero.

10
00:00:25,080 --> 00:00:28,420
However, if you use this function inside a programme,

11
00:00:28,420 --> 00:00:30,860
potentially, you may encounter a problem,

12
00:00:30,860 --> 00:00:34,640
which is that your programme expects the function to work

13
00:00:34,640 --> 00:00:37,690
and there's nothing in the function that says otherwise,

14
00:00:37,690 --> 00:00:38,960
other than a print statement,

15
00:00:38,960 --> 00:00:41,533
which really is meant for your users to see.

16
00:00:43,520 --> 00:00:46,200
For example, let's say that we've got a set of grades

17
00:00:49,170 --> 00:00:51,353
and we want to calculate the average,

18
00:00:54,790 --> 00:00:56,420
and we have a programme like this one.

19
00:00:56,420 --> 00:00:58,170
Welcome to the average grade programme,

20
00:00:58,170 --> 00:01:00,010
and the average is equal to divide

21
00:01:00,010 --> 00:01:01,500
of some grades by len(grades).

22
00:01:01,500 --> 00:01:03,830
Obviously, not the most useful programme,

23
00:01:03,830 --> 00:01:06,540
but just bare with me while I explain why errors

24
00:01:06,540 --> 00:01:08,450
are useful in Python.

25
00:01:08,450 --> 00:01:11,610
What we're gonna get here, if we run this programme

26
00:01:11,610 --> 00:01:16,153
and we print the average grade is average,

27
00:01:17,550 --> 00:01:20,850
is, of course, the average grade.

28
00:01:20,850 --> 00:01:23,610
It says the average grade is 90.5, that's it.

29
00:01:23,610 --> 00:01:24,603
Now, very good.

30
00:01:25,660 --> 00:01:30,660
However, if we want to print a nicer error message,

31
00:01:30,910 --> 00:01:34,160
we start having to do some pretty crazy stuff,

32
00:01:34,160 --> 00:01:36,510
if we are not using errors.

33
00:01:36,510 --> 00:01:39,780
For example, let's say that we don't have any grades yet.

34
00:01:39,780 --> 00:01:42,810
For example, imagine our programme adds the grades over time

35
00:01:42,810 --> 00:01:44,850
or something like that, and there are no grades.

36
00:01:44,850 --> 00:01:48,555
What you'll get is, welcome to the average grade programme,

37
00:01:48,555 --> 00:01:51,093
divisor cannot be zero, the average grade is none.

38
00:01:52,580 --> 00:01:57,160
Now, not the greatest functionality here in our programme,

39
00:01:57,160 --> 00:02:02,160
and this is caused by this function printing something out

40
00:02:03,210 --> 00:02:05,910
that is essentially just mathematical,

41
00:02:05,910 --> 00:02:09,660
it's unrelated to the context of the programme.

42
00:02:09,660 --> 00:02:12,050
This programme here talks about student grades,

43
00:02:12,050 --> 00:02:15,080
and that's what the user is expecting to read about.

44
00:02:15,080 --> 00:02:17,030
This programme here, or this bit of code here,

45
00:02:17,030 --> 00:02:18,210
talks about mathematics,

46
00:02:18,210 --> 00:02:21,320
whether you can divide a number by zero or not.

47
00:02:21,320 --> 00:02:23,840
Though they are related, but you don't wanna be

48
00:02:23,840 --> 00:02:27,190
printing divisor cannot be zero, when the user is expecting

49
00:02:27,190 --> 00:02:29,023
an average of a bunch of grades.

50
00:02:30,310 --> 00:02:33,820
However, it is the only way that we can do something

51
00:02:33,820 --> 00:02:37,910
unless we check for the divisor being zero out here.

52
00:02:37,910 --> 00:02:42,070
So if we say, if len(grades) equal zero,

53
00:02:42,070 --> 00:02:44,190
then you can say you don't have any grades.

54
00:02:44,190 --> 00:02:46,263
You don't have grades yet.

55
00:02:48,150 --> 00:02:50,660
Or we could do this instead, and then,

56
00:02:50,660 --> 00:02:53,440
if you want, you can also put that same check here,

57
00:02:53,440 --> 00:02:54,800
you don't need this return.

58
00:02:54,800 --> 00:02:56,700
But as you can see, this is getting a little bit messy now,

59
00:02:56,700 --> 00:03:01,700
because you are removing logic from a division function

60
00:03:01,740 --> 00:03:03,240
that really should be in there,

61
00:03:03,240 --> 00:03:04,453
or it could be in there,

62
00:03:05,370 --> 00:03:06,880
and putting it in your main programme.

63
00:03:06,880 --> 00:03:08,400
It's making your main programme longer,

64
00:03:08,400 --> 00:03:10,010
it's making your function shorter,

65
00:03:10,010 --> 00:03:11,683
but it's doing a bit less.

66
00:03:13,033 --> 00:03:16,840
This function here would check for division by zero,

67
00:03:16,840 --> 00:03:18,400
and then do something a bit more useful,

68
00:03:18,400 --> 00:03:19,800
rather than print think out.

69
00:03:21,290 --> 00:03:24,580
So, here come the errors.

70
00:03:24,580 --> 00:03:28,440
In Python, errors are often used for flow control,

71
00:03:28,440 --> 00:03:30,430
very much like if statements.

72
00:03:30,430 --> 00:03:34,260
Though, by allowing your functions to raise errors,

73
00:03:34,260 --> 00:03:36,380
you're going to then be able to catch them

74
00:03:36,380 --> 00:03:39,240
in your code and handle them.

75
00:03:39,240 --> 00:03:41,963
Here's what we're gonna do, if divisor == 0,

76
00:03:43,420 --> 00:03:45,630
now we are going to raise something

77
00:03:45,630 --> 00:03:47,410
called a ZeroDivisionError,

78
00:03:47,410 --> 00:03:49,220
which is a error that comes with Python,

79
00:03:49,220 --> 00:03:52,433
and you're gonna say divisor cannot be zero.

80
00:03:53,360 --> 00:03:57,440
Now, this message here inside the brackets means

81
00:03:57,440 --> 00:04:01,153
that this error is going to have a message attached to it.

82
00:04:02,150 --> 00:04:04,200
And what we're doing here is we're saying raise,

83
00:04:04,200 --> 00:04:05,490
the keyword raise and a space,

84
00:04:05,490 --> 00:04:08,100
and then the exception name or the error name,

85
00:04:08,100 --> 00:04:10,230
exception and errors are the same thing,

86
00:04:10,230 --> 00:04:11,280
and then the bracket.

87
00:04:11,280 --> 00:04:14,880
So we're creating an exception object in here.

88
00:04:14,880 --> 00:04:17,833
This is another class that is defined inside Python.

89
00:04:18,980 --> 00:04:22,800
So if we try now to divide the sum of grades

90
00:04:22,800 --> 00:04:25,850
by the len of grades, knowing that there are no grades,

91
00:04:25,850 --> 00:04:28,040
what you're gonna get is,

92
00:04:28,040 --> 00:04:30,190
welcome to the average grade programme.

93
00:04:30,190 --> 00:04:34,720
And then you're going to get a very nice traceback.

94
00:04:34,720 --> 00:04:37,260
So let me just make that a bit bigger for you.

95
00:04:37,260 --> 00:04:41,160
A traceback shows you where the problem happened.

96
00:04:41,160 --> 00:04:45,760
And here it says that the last set of lines here

97
00:04:45,760 --> 00:04:48,460
tells you where the error originated,

98
00:04:48,460 --> 00:04:50,740
and it says it originated in code.py,

99
00:04:50,740 --> 00:04:52,250
which is our file, line three,

100
00:04:52,250 --> 00:04:55,730
which is this one here, in the divide function.

101
00:04:55,730 --> 00:04:58,540
And the problem was that you raised the error yourself.

102
00:04:58,540 --> 00:05:01,190
So because you raised an error the error happened.

103
00:05:01,190 --> 00:05:02,480
If you didn't raise the error

104
00:05:02,480 --> 00:05:03,940
the error wouldn't have happened,

105
00:05:03,940 --> 00:05:05,835
so that it what it's telling you there.

106
00:05:05,835 --> 00:05:08,510
And then it's saying that the next thing up,

107
00:05:08,510 --> 00:05:11,220
what called this divide function,

108
00:05:11,220 --> 00:05:13,720
was this line here, line 11.

109
00:05:13,720 --> 00:05:15,000
And it's showing you the line there

110
00:05:15,000 --> 00:05:17,870
that caused this function to be called,

111
00:05:17,870 --> 00:05:19,220
which then caused the exception.

112
00:05:19,220 --> 00:05:21,150
So you can see how it bubbles up,

113
00:05:21,150 --> 00:05:23,070
and in our case it's only got two lines here,

114
00:05:23,070 --> 00:05:24,870
but sometimes these can be really long,

115
00:05:24,870 --> 00:05:26,500
and they can tell you, this called that

116
00:05:26,500 --> 00:05:27,567
and that called that, and that called that,

117
00:05:27,567 --> 00:05:29,890
and so on, and eventually an error happened.

118
00:05:29,890 --> 00:05:30,990
And what you've got at the very end

119
00:05:30,990 --> 00:05:33,670
is the error itself, a ZeroDivisionError,

120
00:05:33,670 --> 00:05:34,943
divisor cannot be zero.

121
00:05:36,020 --> 00:05:38,630
Clearly we don't wanna be showing our users this,

122
00:05:38,630 --> 00:05:41,930
but this is excellent and really helpful

123
00:05:41,930 --> 00:05:42,860
for when you're coding.

124
00:05:42,860 --> 00:05:45,640
So errors help you track down problems

125
00:05:45,640 --> 00:05:47,690
and where and why they happened.

126
00:05:47,690 --> 00:05:51,540
So errors give developers a great tool for debugging,

127
00:05:51,540 --> 00:05:53,170
or finding where the problem is.

128
00:05:53,170 --> 00:05:56,840
So that's one great plus of using errors.

129
00:05:56,840 --> 00:06:00,220
The other thing is that now you can catch the error.

130
00:06:00,220 --> 00:06:03,430
You can say, okay, if an error happens in this line

131
00:06:03,430 --> 00:06:05,440
I wanna do something.

132
00:06:05,440 --> 00:06:09,300
And the syntax for that in Python is a try-except block.

133
00:06:09,300 --> 00:06:11,740
So we're going to try to do that,

134
00:06:11,740 --> 00:06:14,790
and then if a ZeroDivisionError happens,

135
00:06:14,790 --> 00:06:18,713
then we can print, there are no grades yet in your list.

136
00:06:21,450 --> 00:06:24,270
So, try, and then in an indented block,

137
00:06:24,270 --> 00:06:25,800
we put the code that we wanna try,

138
00:06:25,800 --> 00:06:27,940
this can be one line or it can be many lines.

139
00:06:27,940 --> 00:06:31,410
And then in the same indentation level as the try,

140
00:06:31,410 --> 00:06:34,190
we put except and the type of exception

141
00:06:34,190 --> 00:06:35,850
that we wanna look out for.

142
00:06:35,850 --> 00:06:38,800
If this exception happens in this code,

143
00:06:38,800 --> 00:06:41,290
then we will run this stuff here.

144
00:06:41,290 --> 00:06:46,180
So now our code can handle this ZeroDivisionError,

145
00:06:46,180 --> 00:06:48,570
meaning that if we get a ZeroDivisionError,

146
00:06:48,570 --> 00:06:51,140
we're not going to print the traceback,

147
00:06:51,140 --> 00:06:53,810
we are not going to print divisor cannot be zero.

148
00:06:53,810 --> 00:06:56,530
We are going to print, there are no grades yet in your list.

149
00:06:56,530 --> 00:06:58,830
However, if you use the divide function

150
00:06:58,830 --> 00:06:59,980
somewhere else in your programme

151
00:06:59,980 --> 00:07:03,370
and you don't wrap it in a try-except block,

152
00:07:03,370 --> 00:07:05,510
the error will still happen and the divisor cannot be zero

153
00:07:05,510 --> 00:07:08,173
will still be printed out, and the traceback.

154
00:07:09,060 --> 00:07:12,040
So this allows you to handle these errors

155
00:07:12,040 --> 00:07:13,810
in different ways throughout your programme,

156
00:07:13,810 --> 00:07:16,250
which means that this divide function

157
00:07:16,250 --> 00:07:19,530
is concerned about the mathematics of division,

158
00:07:19,530 --> 00:07:21,120
this piece of code here is concerned

159
00:07:21,120 --> 00:07:22,750
about how to handle the mathematics

160
00:07:22,750 --> 00:07:24,550
in the context of your programme,

161
00:07:24,550 --> 00:07:26,850
which is there are no grades yet in your list.

162
00:07:27,760 --> 00:07:28,967
Notice that here in the except block

163
00:07:28,967 --> 00:07:32,680
you can do as e, and what this does in Python

164
00:07:32,680 --> 00:07:35,340
is it creates a variable called e,

165
00:07:35,340 --> 00:07:39,130
and puts inside it the value of the error, if there is one.

166
00:07:39,130 --> 00:07:42,970
So if the ZeroDivisionError is created with this message,

167
00:07:42,970 --> 00:07:44,990
then e will contain that.

168
00:07:44,990 --> 00:07:46,450
And e can be anything you want,

169
00:07:46,450 --> 00:07:48,060
so you can call it exception,

170
00:07:48,060 --> 00:07:50,910
or you can call it e, or you can call it Bob if you want.

171
00:07:51,760 --> 00:07:53,740
And we can print e as well, if you like,

172
00:07:53,740 --> 00:07:58,740
just to see what happens, and what you get is this stuff.

173
00:07:58,750 --> 00:08:01,490
So you get there are no grades yet in your list,

174
00:08:01,490 --> 00:08:04,123
and you get divisor cannot be zero.

175
00:08:06,100 --> 00:08:09,133
Afterwards, because there was an error in this line,

176
00:08:10,440 --> 00:08:12,780
the average variable was never created,

177
00:08:12,780 --> 00:08:14,660
because this caused the error,

178
00:08:14,660 --> 00:08:16,843
which means our code jumped directly here.

179
00:08:17,780 --> 00:08:21,913
So, when you run line 17, the variable does not exist.

180
00:08:22,890 --> 00:08:27,120
Therefore, you may wanna put your variable in the same block

181
00:08:27,120 --> 00:08:28,960
as your variable definition.

182
00:08:28,960 --> 00:08:31,940
Now running that will give you,

183
00:08:31,940 --> 00:08:33,210
welcome to the average grade programme,

184
00:08:33,210 --> 00:08:36,060
divisor cannot be zero, there are no grades in your list.

185
00:08:37,410 --> 00:08:40,430
If you remove this print e, then that will get rid of

186
00:08:40,430 --> 00:08:43,230
the divisor cannot be zero, and you'll get,

187
00:08:43,230 --> 00:08:44,310
Welcome to the average grade programme,

188
00:08:44,310 --> 00:08:46,540
there are no grades yet in your list.

189
00:08:46,540 --> 00:08:48,030
This is exactly what we wanted,

190
00:08:48,030 --> 00:08:50,870
and using errors allows our programme to handle

191
00:08:50,870 --> 00:08:52,860
both the maths of the operation

192
00:08:52,860 --> 00:08:55,303
and also the programme context.

193
00:08:56,680 --> 00:08:58,162
As well as ZeroDivisionErrors,

194
00:08:58,162 --> 00:09:00,440
there's a whole bunch more built-in errors,

195
00:09:00,440 --> 00:09:01,690
errors that come with Python,

196
00:09:01,690 --> 00:09:04,000
that you can create for different things.

197
00:09:04,000 --> 00:09:06,300
All errors are handled the same way,

198
00:09:06,300 --> 00:09:08,040
but when you see in your programme

199
00:09:08,040 --> 00:09:10,070
that a ZeroDivisionError has happened,

200
00:09:10,070 --> 00:09:11,540
it tells you that you probably tried

201
00:09:11,540 --> 00:09:13,350
to divide something by zero.

202
00:09:13,350 --> 00:09:14,630
Know there are other types of errors,

203
00:09:14,630 --> 00:09:17,300
so that you as the programmer can more easily tell

204
00:09:17,300 --> 00:09:19,010
what happened and what went wrong.

205
00:09:19,010 --> 00:09:21,650
Some examples are a TypeError,

206
00:09:21,650 --> 00:09:23,010
or when something was the wrong type,

207
00:09:23,010 --> 00:09:26,330
and you would raise a TypeError, that.

208
00:09:26,330 --> 00:09:28,900
You've got ValueError, or when something

209
00:09:28,900 --> 00:09:31,560
had the wrong value, or an unexpected value.

210
00:09:31,560 --> 00:09:35,350
You've got RuntimeError, or most other things.

211
00:09:35,350 --> 00:09:37,990
And you can also create your own errors,

212
00:09:37,990 --> 00:09:40,250
but we're going to be doing that in the next video.

213
00:09:40,250 --> 00:09:44,170
Finally, instead of putting this line of code here

214
00:09:44,170 --> 00:09:48,860
together with the try, you can actually put it afterwards,

215
00:09:48,860 --> 00:09:53,770
but tell Python to only run it if this succeeded.

216
00:09:53,770 --> 00:09:54,950
So the way you do that in Python

217
00:09:54,950 --> 00:09:58,220
is you put an else, actually, in there.

218
00:09:58,220 --> 00:10:01,180
And you put this line of code in here.

219
00:10:01,180 --> 00:10:04,420
So this is a different way of running that same code,

220
00:10:04,420 --> 00:10:07,800
and what happens here is you try to run this,

221
00:10:07,800 --> 00:10:10,420
if an error happened then you run this,

222
00:10:10,420 --> 00:10:13,600
and if no error happened that means that this line of code

223
00:10:13,600 --> 00:10:17,410
ran successfully, then you run this.

224
00:10:17,410 --> 00:10:20,330
So the reason why we may wanna use the else,

225
00:10:20,330 --> 00:10:22,550
instead of putting this line of code here,

226
00:10:22,550 --> 00:10:26,130
is if we want to catch some specific errors

227
00:10:26,130 --> 00:10:28,240
in a specific line of code, and we don't wanna put

228
00:10:28,240 --> 00:10:31,470
all of our code in the same block.

229
00:10:31,470 --> 00:10:34,110
Finally, if you wanna run a piece of code always,

230
00:10:34,110 --> 00:10:36,850
no matter whether there is an error, or no error,

231
00:10:36,850 --> 00:10:39,820
you can use the finally clause here

232
00:10:41,460 --> 00:10:42,790
to print something else out,

233
00:10:42,790 --> 00:10:44,110
or you need to do anything else.

234
00:10:44,110 --> 00:10:45,920
So these are the different clauses,

235
00:10:45,920 --> 00:10:50,313
try, except, else and finally, and they run in that order.

236
00:10:51,200 --> 00:10:56,200
You can have multiple except clauses if you want.

237
00:10:56,860 --> 00:10:59,770
For example, if this function here could raise

238
00:10:59,770 --> 00:11:02,440
a ZeroDivisionError, or potentially somewhere else,

239
00:11:02,440 --> 00:11:03,950
it could raise a ValueError,

240
00:11:03,950 --> 00:11:05,710
you can catch them separately,

241
00:11:05,710 --> 00:11:07,923
and handle them differently if you want.

242
00:11:09,090 --> 00:11:10,270
I'm just showing you the syntax there,

243
00:11:10,270 --> 00:11:13,840
but we're gonna look as some examples in just a moment.

244
00:11:13,840 --> 00:11:16,160
Imagine you have a list of students

245
00:11:16,160 --> 00:11:18,163
and each one has a bunch of grades,

246
00:11:18,163 --> 00:11:21,890
here is when using this function might come in handy.

247
00:11:21,890 --> 00:11:23,330
'Cause you've got Bob, Rolf, and Jen,

248
00:11:23,330 --> 00:11:25,730
and Rolf doesn't have any grades.

249
00:11:25,730 --> 00:11:29,380
Though we can try to iterate over the student's list,

250
00:11:29,380 --> 00:11:31,670
get the name and grades, and calculate the average

251
00:11:31,670 --> 00:11:35,250
for a given student, printing their average afterwards.

252
00:11:35,250 --> 00:11:38,090
Of course, Rolf's average will fail,

253
00:11:38,090 --> 00:11:40,600
though we can except in a ZeroDivisionRrror,

254
00:11:40,600 --> 00:11:44,220
and say, error, Rolf has no grades.

255
00:11:44,220 --> 00:11:46,440
Otherwise, if all of them have grades,

256
00:11:46,440 --> 00:11:48,770
we can print that all the student averages

257
00:11:48,770 --> 00:11:51,750
were calculated and finally at the end, no matter what,

258
00:11:51,750 --> 00:11:54,900
we can print the end of the student average calculation.

259
00:11:54,900 --> 00:11:56,800
So if we run this we will encounter an error,

260
00:11:56,800 --> 00:12:00,760
we will print Bob's average and then Rolf will error as out.

261
00:12:00,760 --> 00:12:03,710
Note, Bob averaged 82.5 and we get an error,

262
00:12:03,710 --> 00:12:05,110
Rolf has no grades.

263
00:12:05,110 --> 00:12:08,960
But if we put a grade for Rolf and we press play again,

264
00:12:08,960 --> 00:12:11,060
now you see that all of them run to completion

265
00:12:11,060 --> 00:12:12,510
and we get back a message saying

266
00:12:12,510 --> 00:12:14,790
that all student averages were calculated,

267
00:12:14,790 --> 00:12:17,120
because that's in our else.

268
00:12:17,120 --> 00:12:20,890
So to recap, a try allows you to run a piece of code,

269
00:12:20,890 --> 00:12:24,100
then you can catch or except some exception,

270
00:12:24,100 --> 00:12:25,760
or multiple exceptions if you want,

271
00:12:25,760 --> 00:12:28,660
handling them in that block of code.

272
00:12:28,660 --> 00:12:31,160
The else keyword, together with try and except,

273
00:12:31,160 --> 00:12:34,960
allows you to run some code if there are no errors.

274
00:12:34,960 --> 00:12:37,470
And finally, you can run a piece of code at the very end,

275
00:12:37,470 --> 00:12:40,340
no matter what, whether there's an error, or not,

276
00:12:40,340 --> 00:12:41,590
in case you wanna print a message,

277
00:12:41,590 --> 00:12:43,140
or do some clean up at the end.

278
00:12:44,030 --> 00:12:46,110
That's it for this video, thank you for joining me,

279
00:12:46,110 --> 00:12:47,760
and I'll see you in the next one.

