1
1

00:00:01,310  -->  00:00:02,740
<v ->Hi, guys, and welcome back.</v>
2

2

00:00:02,740  -->  00:00:05,973
In this video, we're going to learn about errors in Python.
3

3

00:00:07,020  -->  00:00:10,060
What we've got here is a simple divide function,
4

4

00:00:10,060  -->  00:00:11,700
that takes in two parameters.
5

5

00:00:11,700  -->  00:00:13,100
If the divisor is equal to zero,
6

6

00:00:13,100  -->  00:00:15,740
it prints that it cannot be zero and then returns.
7

7

00:00:15,740  -->  00:00:19,480
Otherwise, it'll return the dividend divided by the divisor.
8

8

00:00:19,480  -->  00:00:22,780
If we run this code, you should see that you get a print,
9

9

00:00:22,780  -->  00:00:25,080
Divisor cannot be zero.
10

10

00:00:25,080  -->  00:00:28,420
However, if you use this function inside a programme,
11

11

00:00:28,420  -->  00:00:30,860
potentially, you may encounter a problem,
12

12

00:00:30,860  -->  00:00:34,640
which is that your programme expects the function to work
13

13

00:00:34,640  -->  00:00:37,690
and there's nothing in the function that says otherwise,
14

14

00:00:37,690  -->  00:00:38,960
other than a print statement,
15

15

00:00:38,960  -->  00:00:41,533
which really is meant for your users to see.
16

16

00:00:43,520  -->  00:00:46,200
For example, let's say that we've got a set of grades
17

17

00:00:49,170  -->  00:00:51,353
and we want to calculate the average,
18

18

00:00:54,790  -->  00:00:56,420
and we have a programme like this one.
19

19

00:00:56,420  -->  00:00:58,170
Welcome to the average grade programme,
20

20

00:00:58,170  -->  00:01:00,010
and the average is equal to divide
21

21

00:01:00,010  -->  00:01:01,500
of some grades by len(grades).
22

22

00:01:01,500  -->  00:01:03,830
Obviously, not the most useful programme,
23

23

00:01:03,830  -->  00:01:06,540
but just bare with me while I explain why errors
24

24

00:01:06,540  -->  00:01:08,450
are useful in Python.
25

25

00:01:08,450  -->  00:01:11,610
What we're gonna get here, if we run this programme
26

26

00:01:11,610  -->  00:01:16,153
and we print the average grade is average,
27

27

00:01:17,550  -->  00:01:20,850
is, of course, the average grade.
28

28

00:01:20,850  -->  00:01:23,610
It says the average grade is 90.5, that's it.
29

29

00:01:23,610  -->  00:01:24,603
Now, very good.
30

30

00:01:25,660  -->  00:01:30,660
However, if we want to print a nicer error message,
31

31

00:01:30,910  -->  00:01:34,160
we start having to do some pretty crazy stuff,
32

32

00:01:34,160  -->  00:01:36,510
if we are not using errors.
33

33

00:01:36,510  -->  00:01:39,780
For example, let's say that we don't have any grades yet.
34

34

00:01:39,780  -->  00:01:42,810
For example, imagine our programme adds the grades over time
35

35

00:01:42,810  -->  00:01:44,850
or something like that, and there are no grades.
36

36

00:01:44,850  -->  00:01:48,555
What you'll get is, welcome to the average grade programme,
37

37

00:01:48,555  -->  00:01:51,093
divisor cannot be zero, the average grade is none.
38

38

00:01:52,580  -->  00:01:57,160
Now, not the greatest functionality here in our programme,
39

39

00:01:57,160  -->  00:02:02,160
and this is caused by this function printing something out
40

40

00:02:03,210  -->  00:02:05,910
that is essentially just mathematical,
41

41

00:02:05,910  -->  00:02:09,660
it's unrelated to the context of the programme.
42

42

00:02:09,660  -->  00:02:12,050
This programme here talks about student grades,
43

43

00:02:12,050  -->  00:02:15,080
and that's what the user is expecting to read about.
44

44

00:02:15,080  -->  00:02:17,030
This programme here, or this bit of code here,
45

45

00:02:17,030  -->  00:02:18,210
talks about mathematics,
46

46

00:02:18,210  -->  00:02:21,320
whether you can divide a number by zero or not.
47

47

00:02:21,320  -->  00:02:23,840
Though they are related, but you don't wanna be
48

48

00:02:23,840  -->  00:02:27,190
printing divisor cannot be zero, when the user is expecting
49

49

00:02:27,190  -->  00:02:29,023
an average of a bunch of grades.
50

50

00:02:30,310  -->  00:02:33,820
However, it is the only way that we can do something
51

51

00:02:33,820  -->  00:02:37,910
unless we check for the divisor being zero out here.
52

52

00:02:37,910  -->  00:02:42,070
So if we say, if len(grades) equal zero,
53

53

00:02:42,070  -->  00:02:44,190
then you can say you don't have any grades.
54

54

00:02:44,190  -->  00:02:46,263
You don't have grades yet.
55

55

00:02:48,150  -->  00:02:50,660
Or we could do this instead, and then,
56

56

00:02:50,660  -->  00:02:53,440
if you want, you can also put that same check here,
57

57

00:02:53,440  -->  00:02:54,800
you don't need this return.
58

58

00:02:54,800  -->  00:02:56,700
But as you can see, this is getting a little bit messy now,
59

59

00:02:56,700  -->  00:03:01,700
because you are removing logic from a division function
60

60

00:03:01,740  -->  00:03:03,240
that really should be in there,
61

61

00:03:03,240  -->  00:03:04,453
or it could be in there,
62

62

00:03:05,370  -->  00:03:06,880
and putting it in your main programme.
63

63

00:03:06,880  -->  00:03:08,400
It's making your main programme longer,
64

64

00:03:08,400  -->  00:03:10,010
it's making your function shorter,
65

65

00:03:10,010  -->  00:03:11,683
but it's doing a bit less.
66

66

00:03:13,033  -->  00:03:16,840
This function here would check for division by zero,
67

67

00:03:16,840  -->  00:03:18,400
and then do something a bit more useful,
68

68

00:03:18,400  -->  00:03:19,800
rather than print think out.
69

69

00:03:21,290  -->  00:03:24,580
So, here come the errors.
70

70

00:03:24,580  -->  00:03:28,440
In Python, errors are often used for flow control,
71

71

00:03:28,440  -->  00:03:30,430
very much like if statements.
72

72

00:03:30,430  -->  00:03:34,260
Though, by allowing your functions to raise errors,
73

73

00:03:34,260  -->  00:03:36,380
you're going to then be able to catch them
74

74

00:03:36,380  -->  00:03:39,240
in your code and handle them.
75

75

00:03:39,240  -->  00:03:41,963
Here's what we're gonna do, if divisor == 0,
76

76

00:03:43,420  -->  00:03:45,630
now we are going to raise something
77

77

00:03:45,630  -->  00:03:47,410
called a ZeroDivisionError,
78

78

00:03:47,410  -->  00:03:49,220
which is a error that comes with Python,
79

79

00:03:49,220  -->  00:03:52,433
and you're gonna say divisor cannot be zero.
80

80

00:03:53,360  -->  00:03:57,440
Now, this message here inside the brackets means
81

81

00:03:57,440  -->  00:04:01,153
that this error is going to have a message attached to it.
82

82

00:04:02,150  -->  00:04:04,200
And what we're doing here is we're saying raise,
83

83

00:04:04,200  -->  00:04:05,490
the keyword raise and a space,
84

84

00:04:05,490  -->  00:04:08,100
and then the exception name or the error name,
85

85

00:04:08,100  -->  00:04:10,230
exception and errors are the same thing,
86

86

00:04:10,230  -->  00:04:11,280
and then the bracket.
87

87

00:04:11,280  -->  00:04:14,880
So we're creating an exception object in here.
88

88

00:04:14,880  -->  00:04:17,833
This is another class that is defined inside Python.
89

89

00:04:18,980  -->  00:04:22,800
So if we try now to divide the sum of grades
90

90

00:04:22,800  -->  00:04:25,850
by the len of grades, knowing that there are no grades,
91

91

00:04:25,850  -->  00:04:28,040
what you're gonna get is,
92

92

00:04:28,040  -->  00:04:30,190
welcome to the average grade programme.
93

93

00:04:30,190  -->  00:04:34,720
And then you're going to get a very nice traceback.
94

94

00:04:34,720  -->  00:04:37,260
So let me just make that a bit bigger for you.
95

95

00:04:37,260  -->  00:04:41,160
A traceback shows you where the problem happened.
96

96

00:04:41,160  -->  00:04:45,760
And here it says that the last set of lines here
97

97

00:04:45,760  -->  00:04:48,460
tells you where the error originated,
98

98

00:04:48,460  -->  00:04:50,740
and it says it originated in code.py,
99

99

00:04:50,740  -->  00:04:52,250
which is our file, line three,
100

100

00:04:52,250  -->  00:04:55,730
which is this one here, in the divide function.
101

101

00:04:55,730  -->  00:04:58,540
And the problem was that you raised the error yourself.
102

102

00:04:58,540  -->  00:05:01,190
So because you raised an error the error happened.
103

103

00:05:01,190  -->  00:05:02,480
If you didn't raise the error
104

104

00:05:02,480  -->  00:05:03,940
the error wouldn't have happened,
105

105

00:05:03,940  -->  00:05:05,835
so that it what it's telling you there.
106

106

00:05:05,835  -->  00:05:08,510
And then it's saying that the next thing up,
107

107

00:05:08,510  -->  00:05:11,220
what called this divide function,
108

108

00:05:11,220  -->  00:05:13,720
was this line here, line 11.
109

109

00:05:13,720  -->  00:05:15,000
And it's showing you the line there
110

110

00:05:15,000  -->  00:05:17,870
that caused this function to be called,
111

111

00:05:17,870  -->  00:05:19,220
which then caused the exception.
112

112

00:05:19,220  -->  00:05:21,150
So you can see how it bubbles up,
113

113

00:05:21,150  -->  00:05:23,070
and in our case it's only got two lines here,
114

114

00:05:23,070  -->  00:05:24,870
but sometimes these can be really long,
115

115

00:05:24,870  -->  00:05:26,500
and they can tell you, this called that
116

116

00:05:26,500  -->  00:05:27,567
and that called that, and that called that,
117

117

00:05:27,567  -->  00:05:29,890
and so on, and eventually an error happened.
118

118

00:05:29,890  -->  00:05:30,990
And what you've got at the very end
119

119

00:05:30,990  -->  00:05:33,670
is the error itself, a ZeroDivisionError,
120

120

00:05:33,670  -->  00:05:34,943
divisor cannot be zero.
121

121

00:05:36,020  -->  00:05:38,630
Clearly we don't wanna be showing our users this,
122

122

00:05:38,630  -->  00:05:41,930
but this is excellent and really helpful
123

123

00:05:41,930  -->  00:05:42,860
for when you're coding.
124

124

00:05:42,860  -->  00:05:45,640
So errors help you track down problems
125

125

00:05:45,640  -->  00:05:47,690
and where and why they happened.
126

126

00:05:47,690  -->  00:05:51,540
So errors give developers a great tool for debugging,
127

127

00:05:51,540  -->  00:05:53,170
or finding where the problem is.
128

128

00:05:53,170  -->  00:05:56,840
So that's one great plus of using errors.
129

129

00:05:56,840  -->  00:06:00,220
The other thing is that now you can catch the error.
130

130

00:06:00,220  -->  00:06:03,430
You can say, okay, if an error happens in this line
131

131

00:06:03,430  -->  00:06:05,440
I wanna do something.
132

132

00:06:05,440  -->  00:06:09,300
And the syntax for that in Python is a try-except block.
133

133

00:06:09,300  -->  00:06:11,740
So we're going to try to do that,
134

134

00:06:11,740  -->  00:06:14,790
and then if a ZeroDivisionError happens,
135

135

00:06:14,790  -->  00:06:18,713
then we can print, there are no grades yet in your list.
136

136

00:06:21,450  -->  00:06:24,270
So, try, and then in an indented block,
137

137

00:06:24,270  -->  00:06:25,800
we put the code that we wanna try,
138

138

00:06:25,800  -->  00:06:27,940
this can be one line or it can be many lines.
139

139

00:06:27,940  -->  00:06:31,410
And then in the same indentation level as the try,
140

140

00:06:31,410  -->  00:06:34,190
we put except and the type of exception
141

141

00:06:34,190  -->  00:06:35,850
that we wanna look out for.
142

142

00:06:35,850  -->  00:06:38,800
If this exception happens in this code,
143

143

00:06:38,800  -->  00:06:41,290
then we will run this stuff here.
144

144

00:06:41,290  -->  00:06:46,180
So now our code can handle this ZeroDivisionError,
145

145

00:06:46,180  -->  00:06:48,570
meaning that if we get a ZeroDivisionError,
146

146

00:06:48,570  -->  00:06:51,140
we're not going to print the traceback,
147

147

00:06:51,140  -->  00:06:53,810
we are not going to print divisor cannot be zero.
148

148

00:06:53,810  -->  00:06:56,530
We are going to print, there are no grades yet in your list.
149

149

00:06:56,530  -->  00:06:58,830
However, if you use the divide function
150

150

00:06:58,830  -->  00:06:59,980
somewhere else in your programme
151

151

00:06:59,980  -->  00:07:03,370
and you don't wrap it in a try-except block,
152

152

00:07:03,370  -->  00:07:05,510
the error will still happen and the divisor cannot be zero
153

153

00:07:05,510  -->  00:07:08,173
will still be printed out, and the traceback.
154

154

00:07:09,060  -->  00:07:12,040
So this allows you to handle these errors
155

155

00:07:12,040  -->  00:07:13,810
in different ways throughout your programme,
156

156

00:07:13,810  -->  00:07:16,250
which means that this divide function
157

157

00:07:16,250  -->  00:07:19,530
is concerned about the mathematics of division,
158

158

00:07:19,530  -->  00:07:21,120
this piece of code here is concerned
159

159

00:07:21,120  -->  00:07:22,750
about how to handle the mathematics
160

160

00:07:22,750  -->  00:07:24,550
in the context of your programme,
161

161

00:07:24,550  -->  00:07:26,850
which is there are no grades yet in your list.
162

162

00:07:27,760  -->  00:07:28,967
Notice that here in the except block
163

163

00:07:28,967  -->  00:07:32,680
you can do as e, and what this does in Python
164

164

00:07:32,680  -->  00:07:35,340
is it creates a variable called e,
165

165

00:07:35,340  -->  00:07:39,130
and puts inside it the value of the error, if there is one.
166

166

00:07:39,130  -->  00:07:42,970
So if the ZeroDivisionError is created with this message,
167

167

00:07:42,970  -->  00:07:44,990
then e will contain that.
168

168

00:07:44,990  -->  00:07:46,450
And e can be anything you want,
169

169

00:07:46,450  -->  00:07:48,060
so you can call it exception,
170

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

171

00:07:51,760  -->  00:07:53,740
And we can print e as well, if you like,
172

172

00:07:53,740  -->  00:07:58,740
just to see what happens, and what you get is this stuff.
173

173

00:07:58,750  -->  00:08:01,490
So you get there are no grades yet in your list,
174

174

00:08:01,490  -->  00:08:04,123
and you get divisor cannot be zero.
175

175

00:08:06,100  -->  00:08:09,133
Afterwards, because there was an error in this line,
176

176

00:08:10,440  -->  00:08:12,780
the average variable was never created,
177

177

00:08:12,780  -->  00:08:14,660
because this caused the error,
178

178

00:08:14,660  -->  00:08:16,843
which means our code jumped directly here.
179

179

00:08:17,780  -->  00:08:21,913
So, when you run line 17, the variable does not exist.
180

180

00:08:22,890  -->  00:08:27,120
Therefore, you may wanna put your variable in the same block
181

181

00:08:27,120  -->  00:08:28,960
as your variable definition.
182

182

00:08:28,960  -->  00:08:31,940
Now running that will give you,
183

183

00:08:31,940  -->  00:08:33,210
welcome to the average grade programme,
184

184

00:08:33,210  -->  00:08:36,060
divisor cannot be zero, there are no grades in your list.
185

185

00:08:37,410  -->  00:08:40,430
If you remove this print e, then that will get rid of
186

186

00:08:40,430  -->  00:08:43,230
the divisor cannot be zero, and you'll get,
187

187

00:08:43,230  -->  00:08:44,310
Welcome to the average grade programme,
188

188

00:08:44,310  -->  00:08:46,540
there are no grades yet in your list.
189

189

00:08:46,540  -->  00:08:48,030
This is exactly what we wanted,
190

190

00:08:48,030  -->  00:08:50,870
and using errors allows our programme to handle
191

191

00:08:50,870  -->  00:08:52,860
both the maths of the operation
192

192

00:08:52,860  -->  00:08:55,303
and also the programme context.
193

193

00:08:56,680  -->  00:08:58,162
As well as ZeroDivisionErrors,
194

194

00:08:58,162  -->  00:09:00,440
there's a whole bunch more built-in errors,
195

195

00:09:00,440  -->  00:09:01,690
errors that come with Python,
196

196

00:09:01,690  -->  00:09:04,000
that you can create for different things.
197

197

00:09:04,000  -->  00:09:06,300
All errors are handled the same way,
198

198

00:09:06,300  -->  00:09:08,040
but when you see in your programme
199

199

00:09:08,040  -->  00:09:10,070
that a ZeroDivisionError has happened,
200

200

00:09:10,070  -->  00:09:11,540
it tells you that you probably tried
201

201

00:09:11,540  -->  00:09:13,350
to divide something by zero.
202

202

00:09:13,350  -->  00:09:14,630
Know there are other types of errors,
203

203

00:09:14,630  -->  00:09:17,300
so that you as the programmer can more easily tell
204

204

00:09:17,300  -->  00:09:19,010
what happened and what went wrong.
205

205

00:09:19,010  -->  00:09:21,650
Some examples are a TypeError,
206

206

00:09:21,650  -->  00:09:23,010
or when something was the wrong type,
207

207

00:09:23,010  -->  00:09:26,330
and you would raise a TypeError, that.
208

208

00:09:26,330  -->  00:09:28,900
You've got ValueError, or when something
209

209

00:09:28,900  -->  00:09:31,560
had the wrong value, or an unexpected value.
210

210

00:09:31,560  -->  00:09:35,350
You've got RuntimeError, or most other things.
211

211

00:09:35,350  -->  00:09:37,990
And you can also create your own errors,
212

212

00:09:37,990  -->  00:09:40,250
but we're going to be doing that in the next video.
213

213

00:09:40,250  -->  00:09:44,170
Finally, instead of putting this line of code here
214

214

00:09:44,170  -->  00:09:48,860
together with the try, you can actually put it afterwards,
215

215

00:09:48,860  -->  00:09:53,770
but tell Python to only run it if this succeeded.
216

216

00:09:53,770  -->  00:09:54,950
So the way you do that in Python
217

217

00:09:54,950  -->  00:09:58,220
is you put an else, actually, in there.
218

218

00:09:58,220  -->  00:10:01,180
And you put this line of code in here.
219

219

00:10:01,180  -->  00:10:04,420
So this is a different way of running that same code,
220

220

00:10:04,420  -->  00:10:07,800
and what happens here is you try to run this,
221

221

00:10:07,800  -->  00:10:10,420
if an error happened then you run this,
222

222

00:10:10,420  -->  00:10:13,600
and if no error happened that means that this line of code
223

223

00:10:13,600  -->  00:10:17,410
ran successfully, then you run this.
224

224

00:10:17,410  -->  00:10:20,330
So the reason why we may wanna use the else,
225

225

00:10:20,330  -->  00:10:22,550
instead of putting this line of code here,
226

226

00:10:22,550  -->  00:10:26,130
is if we want to catch some specific errors
227

227

00:10:26,130  -->  00:10:28,240
in a specific line of code, and we don't wanna put
228

228

00:10:28,240  -->  00:10:31,470
all of our code in the same block.
229

229

00:10:31,470  -->  00:10:34,110
Finally, if you wanna run a piece of code always,
230

230

00:10:34,110  -->  00:10:36,850
no matter whether there is an error, or no error,
231

231

00:10:36,850  -->  00:10:39,820
you can use the finally clause here
232

232

00:10:41,460  -->  00:10:42,790
to print something else out,
233

233

00:10:42,790  -->  00:10:44,110
or you need to do anything else.
234

234

00:10:44,110  -->  00:10:45,920
So these are the different clauses,
235

235

00:10:45,920  -->  00:10:50,313
try, except, else and finally, and they run in that order.
236

236

00:10:51,200  -->  00:10:56,200
You can have multiple except clauses if you want.
237

237

00:10:56,860  -->  00:10:59,770
For example, if this function here could raise
238

238

00:10:59,770  -->  00:11:02,440
a ZeroDivisionError, or potentially somewhere else,
239

239

00:11:02,440  -->  00:11:03,950
it could raise a ValueError,
240

240

00:11:03,950  -->  00:11:05,710
you can catch them separately,
241

241

00:11:05,710  -->  00:11:07,923
and handle them differently if you want.
242

242

00:11:09,090  -->  00:11:10,270
I'm just showing you the syntax there,
243

243

00:11:10,270  -->  00:11:13,840
but we're gonna look as some examples in just a moment.
244

244

00:11:13,840  -->  00:11:16,160
Imagine you have a list of students
245

245

00:11:16,160  -->  00:11:18,163
and each one has a bunch of grades,
246

246

00:11:18,163  -->  00:11:21,890
here is when using this function might come in handy.
247

247

00:11:21,890  -->  00:11:23,330
'Cause you've got Bob, Rolf, and Jen,
248

248

00:11:23,330  -->  00:11:25,730
and Rolf doesn't have any grades.
249

249

00:11:25,730  -->  00:11:29,380
Though we can try to iterate over the student's list,
250

250

00:11:29,380  -->  00:11:31,670
get the name and grades, and calculate the average
251

251

00:11:31,670  -->  00:11:35,250
for a given student, printing their average afterwards.
252

252

00:11:35,250  -->  00:11:38,090
Of course, Rolf's average will fail,
253

253

00:11:38,090  -->  00:11:40,600
though we can except in a ZeroDivisionRrror,
254

254

00:11:40,600  -->  00:11:44,220
and say, error, Rolf has no grades.
255

255

00:11:44,220  -->  00:11:46,440
Otherwise, if all of them have grades,
256

256

00:11:46,440  -->  00:11:48,770
we can print that all the student averages
257

257

00:11:48,770  -->  00:11:51,750
were calculated and finally at the end, no matter what,
258

258

00:11:51,750  -->  00:11:54,900
we can print the end of the student average calculation.
259

259

00:11:54,900  -->  00:11:56,800
So if we run this we will encounter an error,
260

260

00:11:56,800  -->  00:12:00,760
we will print Bob's average and then Rolf will error as out.
261

261

00:12:00,760  -->  00:12:03,710
Note, Bob averaged 82.5 and we get an error,
262

262

00:12:03,710  -->  00:12:05,110
Rolf has no grades.
263

263

00:12:05,110  -->  00:12:08,960
But if we put a grade for Rolf and we press play again,
264

264

00:12:08,960  -->  00:12:11,060
now you see that all of them run to completion
265

265

00:12:11,060  -->  00:12:12,510
and we get back a message saying
266

266

00:12:12,510  -->  00:12:14,790
that all student averages were calculated,
267

267

00:12:14,790  -->  00:12:17,120
because that's in our else.
268

268

00:12:17,120  -->  00:12:20,890
So to recap, a try allows you to run a piece of code,
269

269

00:12:20,890  -->  00:12:24,100
then you can catch or except some exception,
270

270

00:12:24,100  -->  00:12:25,760
or multiple exceptions if you want,
271

271

00:12:25,760  -->  00:12:28,660
handling them in that block of code.
272

272

00:12:28,660  -->  00:12:31,160
The else keyword, together with try and except,
273

273

00:12:31,160  -->  00:12:34,960
allows you to run some code if there are no errors.
274

274

00:12:34,960  -->  00:12:37,470
And finally, you can run a piece of code at the very end,
275

275

00:12:37,470  -->  00:12:40,340
no matter what, whether there's an error, or not,
276

276

00:12:40,340  -->  00:12:41,590
in case you wanna print a message,
277

277

00:12:41,590  -->  00:12:43,140
or do some clean up at the end.
278

278

00:12:44,030  -->  00:12:46,110
That's it for this video, thank you for joining me,
279

279

00:12:46,110  -->  00:12:47,760
and I'll see you in the next one.
