WEBVTT 1 00:00:00.260 --> 00:00:01.440 Hi and welcome back. 2 00:00:01.440 --> 00:00:03.170 In this video, we're talking about creating 3 00:00:03.170 --> 00:00:05.133 our own errors in Python. 4 00:00:06.250 --> 00:00:07.720 Let's go over to our errors project, 5 00:00:07.720 --> 00:00:09.900 and I'm going to create a new file. 6 00:00:09.900 --> 00:00:11.400 I'm gonna call this errors.py. 7 00:00:13.463 --> 00:00:16.050 And now we have ourselves a blank file. 8 00:00:16.050 --> 00:00:18.140 We've looked at how we can raise errors, 9 00:00:18.140 --> 00:00:20.830 but we've only used the built-in errors. 10 00:00:20.830 --> 00:00:23.183 Let's for example raise TypeError. 11 00:00:27.620 --> 00:00:30.560 We've got this type, and we've written a new object of it, 12 00:00:30.560 --> 00:00:31.983 and that's what we raise. 13 00:00:32.930 --> 00:00:36.660 Now, we know how to create a class 14 00:00:36.660 --> 00:00:39.280 that extends everything from another class, 15 00:00:39.280 --> 00:00:40.700 essentially a copy. 16 00:00:40.700 --> 00:00:41.533 How do we create a class 17 00:00:41.533 --> 00:00:43.350 that is essentially a copy of another class? 18 00:00:43.350 --> 00:00:44.683 By using inheritance. 19 00:00:45.620 --> 00:00:48.180 If we had to create a custom error 20 00:00:49.250 --> 00:00:51.460 so that we can do MyCustomError. 21 00:00:54.700 --> 00:00:56.433 Remember this is a class, 22 00:00:57.350 --> 00:01:00.330 and it has to inherit from 23 00:01:01.170 --> 00:01:04.010 one of the built-in errors. 24 00:01:04.010 --> 00:01:06.510 You can pick any you want, for example, TypeError. 25 00:01:08.250 --> 00:01:10.440 Go ahead and pause the video and try to create a class 26 00:01:10.440 --> 00:01:12.220 that would inherit from a TypeError. 27 00:01:12.220 --> 00:01:14.480 How you may go about that? 28 00:01:14.480 --> 00:01:15.330 It's fairly straight-forward, 29 00:01:15.330 --> 00:01:16.930 it'll just be a couple of lines. 30 00:01:21.040 --> 00:01:22.990 Okay, I hope you managed that. 31 00:01:22.990 --> 00:01:25.400 Very straight-forward, but it can be a bit confusing 32 00:01:25.400 --> 00:01:27.970 when you encounter that you have to do something 33 00:01:27.970 --> 00:01:31.050 in a new scenario that you hadn't thought of before. 34 00:01:31.050 --> 00:01:32.840 Creating a class that extends a TypeError 35 00:01:32.840 --> 00:01:36.085 is just like creating a class that extends any other class. 36 00:01:36.085 --> 00:01:38.668 Class MyCustomError, TypeError. 37 00:01:41.840 --> 00:01:44.510 And then of course we need the indented block, 38 00:01:44.510 --> 00:01:47.870 but we can type pass to just pass through 39 00:01:47.870 --> 00:01:48.870 and not do anything. 40 00:01:50.080 --> 00:01:52.750 Now we can raise MyCustomError 41 00:01:52.750 --> 00:01:55.730 because it essentially is a TypeError, 42 00:01:55.730 --> 00:01:57.223 it's just got a new name now. 43 00:01:58.740 --> 00:02:03.100 So we can raise it, let's right-click errors.py and run it. 44 00:02:03.100 --> 00:02:05.640 By the way, if you start getting accustomed 45 00:02:05.640 --> 00:02:08.810 to pressing the Play button up here on the right, 46 00:02:08.810 --> 00:02:12.080 that's fine, but make sure to check what you are running, 47 00:02:12.080 --> 00:02:15.080 which is this thing here, and right now you're running app, 48 00:02:15.080 --> 00:02:18.452 so if you press Play, you're gonna run app.py not errors.py, 49 00:02:18.452 --> 00:02:21.170 so you may want to run errors. 50 00:02:21.170 --> 00:02:25.123 Now notice how you get your MyCustomError thing here, 51 00:02:26.260 --> 00:02:29.100 but it doesn't have a message or anything like that, 52 00:02:29.100 --> 00:02:33.450 and what you then get is __main__.MyCustomError. 53 00:02:37.070 --> 00:02:39.900 Don't worry too much about the main part, 54 00:02:39.900 --> 00:02:42.320 we're going to look into exactly what it means 55 00:02:42.320 --> 00:02:44.170 in the next section, 56 00:02:44.170 --> 00:02:46.810 but just know that you've managed to now raise an error 57 00:02:46.810 --> 00:02:48.840 which is called MyCustomError, 58 00:02:48.840 --> 00:02:50.680 and of course you can put in here 59 00:02:55.040 --> 00:02:57.130 some message, this is a pretty terrible message, 60 00:02:57.130 --> 00:02:58.180 but you know you can. 61 00:02:59.100 --> 00:03:00.480 Now we've made this edit, 62 00:03:00.480 --> 00:03:02.030 and I'd also like to intersperse 63 00:03:02.030 --> 00:03:05.010 into here some PyCharm goodness. 64 00:03:05.010 --> 00:03:09.130 Now our run file has changed to errors.py, 65 00:03:09.130 --> 00:03:11.690 so we can press the Play button up here on the right 66 00:03:11.690 --> 00:03:14.390 or we can press the Play button down here on the left. 67 00:03:15.470 --> 00:03:17.010 And that's fine. 68 00:03:17.010 --> 00:03:18.760 That's gonna re-run that file. 69 00:03:18.760 --> 00:03:21.710 And now you can see that you get a nice description 70 00:03:21.710 --> 00:03:23.823 beside your name of the error. 71 00:03:24.930 --> 00:03:27.733 This is how you can create your custom errors. 72 00:03:28.890 --> 00:03:31.800 Now, of course you can 73 00:03:32.760 --> 00:03:35.830 have a custom error that takes in some more data 74 00:03:35.830 --> 00:03:38.730 other than just a message, 75 00:03:38.730 --> 00:03:41.763 and this is part of the power of these custom errors. 76 00:03:42.660 --> 00:03:45.080 For example, say you want your custom error 77 00:03:45.080 --> 00:03:46.770 to include an error code. 78 00:03:46.770 --> 00:03:47.950 These things are fairly popular, 79 00:03:47.950 --> 00:03:49.720 for example if you've ever got a printer, 80 00:03:49.720 --> 00:03:51.520 you'll know that they give you error codes 81 00:03:51.520 --> 00:03:54.130 all over the place and sometimes it can be useful 82 00:03:54.130 --> 00:03:56.430 to have error codes in your messages. 83 00:03:56.430 --> 00:03:59.550 Now an option is of course to have something 84 00:03:59.550 --> 00:04:04.100 like "Error code 500, OUCH! An error happened.", 85 00:04:04.100 --> 00:04:07.630 but you don't know that this error code is 500 86 00:04:07.630 --> 00:04:09.430 from a programme point of view, 87 00:04:09.430 --> 00:04:10.700 because of course this is a string, 88 00:04:10.700 --> 00:04:13.960 it's just some letters and numbers and symbols 89 00:04:13.960 --> 00:04:15.980 and Python can't interpret it. 90 00:04:15.980 --> 00:04:17.550 If you then wanted to check 91 00:04:17.550 --> 00:04:20.330 whether your error has a code 500 or not, 92 00:04:20.330 --> 00:04:22.120 it would not be so easy. 93 00:04:22.120 --> 00:04:25.500 So instead, the best thing to do is to have two arguments: 94 00:04:25.500 --> 00:04:29.023 the message, and then the code, for example, 500. 95 00:04:30.660 --> 00:04:32.170 But in order to do that, 96 00:04:32.170 --> 00:04:37.060 we have to define a new constructor in MyCustomError, 97 00:04:37.060 --> 00:04:39.220 so let's do that. 98 00:04:39.220 --> 00:04:43.940 And what we want to do is call the super class constructor 99 00:04:43.940 --> 00:04:48.020 with, oh sorry, message, code, 100 00:04:48.020 --> 00:04:50.080 call the super class constructor 101 00:04:50.080 --> 00:04:51.903 with the message as an argument. 102 00:04:53.070 --> 00:04:55.050 Call the super class __init__ method 103 00:04:55.050 --> 00:04:56.880 with the message as an argument, 104 00:04:56.880 --> 00:04:59.070 and then set the code to be a property 105 00:04:59.070 --> 00:05:01.570 of MyCustomError's object. 106 00:05:01.570 --> 00:05:03.643 So pause the video and give that a go. 107 00:05:08.477 --> 00:05:09.760 I hope you managed. 108 00:05:09.760 --> 00:05:12.970 In order to call the __init__ method of the super class, 109 00:05:12.970 --> 00:05:16.380 all we do is __init__ message. 110 00:05:16.380 --> 00:05:19.460 So now we are passing the message parameter 111 00:05:19.460 --> 00:05:21.780 to the __init__ method of the super class 112 00:05:21.780 --> 00:05:23.300 which is TypeError, 113 00:05:23.300 --> 00:05:25.200 and we can also do self.code 114 00:05:26.437 --> 00:05:29.133 = code like that. 115 00:05:31.630 --> 00:05:32.660 You okay? 116 00:05:32.660 --> 00:05:37.660 Now we have this here and we can play the errors file again, 117 00:05:38.600 --> 00:05:42.940 but notice how we don't get any extra information 118 00:05:42.940 --> 00:05:44.260 in the message. 119 00:05:44.260 --> 00:05:46.210 We've got "OUCH! An error happened.", 120 00:05:46.210 --> 00:05:48.850 and we don't know that it's an error code 500, 121 00:05:48.850 --> 00:05:52.260 all we've got is this 500 code on the line 122 00:05:52.260 --> 00:05:53.490 where we actually raise the error, 123 00:05:53.490 --> 00:05:55.510 because this is the line where we raise the error 124 00:05:55.510 --> 00:05:57.900 and we've typed 500 in there. 125 00:05:57.900 --> 00:05:58.883 So what can we do? 126 00:05:59.780 --> 00:06:02.283 Well, we could put the error code in here again. 127 00:06:04.450 --> 00:06:06.640 But of course that's not great 128 00:06:06.640 --> 00:06:08.880 because if you then go and change this one, you say 400, 129 00:06:08.880 --> 00:06:11.360 then you also have to go here and change the string. 130 00:06:11.360 --> 00:06:13.210 So not fantastic. 131 00:06:13.210 --> 00:06:14.750 We don't want to do that. 132 00:06:14.750 --> 00:06:19.750 What can we do instead in order to include this error code 133 00:06:19.830 --> 00:06:21.530 inside the message? 134 00:06:21.530 --> 00:06:23.070 I hope you managed that, 135 00:06:23.070 --> 00:06:25.790 all you have to do is, when I show you, 136 00:06:25.790 --> 00:06:28.660 if you didn't quite manage it's fairly obvious, 137 00:06:28.660 --> 00:06:31.140 but of course you have to think in this way. 138 00:06:31.140 --> 00:06:32.650 You just want to create a new string 139 00:06:32.650 --> 00:06:37.450 that says "Error code {code}: {message}". 140 00:06:38.900 --> 00:06:39.733 That's it. 141 00:06:41.230 --> 00:06:44.810 We're just creating a new string which will now replace 142 00:06:44.810 --> 00:06:47.930 the message we got in by this other string 143 00:06:47.930 --> 00:06:49.873 that contains the error code as well. 144 00:06:51.550 --> 00:06:56.550 And in order to begin thinking this way, that takes time, 145 00:06:58.020 --> 00:07:00.900 that you can essentially do anything you want. 146 00:07:00.900 --> 00:07:05.270 All that's happening in these method calls, 147 00:07:05.270 --> 00:07:06.310 calling the __init__ method 148 00:07:06.310 --> 00:07:08.380 and raising and things like that, 149 00:07:08.380 --> 00:07:10.430 data is moving from one place to another. 150 00:07:11.320 --> 00:07:12.713 You've got this string, 151 00:07:13.620 --> 00:07:16.810 and that string is now being assigned to message. 152 00:07:16.810 --> 00:07:19.260 Then that message was gonna go over to this __init__ method, 153 00:07:19.260 --> 00:07:21.390 where it was gonna be assigned to something else. 154 00:07:21.390 --> 00:07:25.420 Someplace in Python's code that message was gonna be used 155 00:07:25.420 --> 00:07:27.920 in order to print it out to the console. 156 00:07:27.920 --> 00:07:30.323 But that is just a string. 157 00:07:31.840 --> 00:07:33.197 If you can put a string in there, 158 00:07:33.197 --> 00:07:36.070 you can put any string value you want, 159 00:07:36.070 --> 00:07:38.210 which means you can modify it here 160 00:07:38.210 --> 00:07:40.410 and just pass in slightly different data. 161 00:07:40.410 --> 00:07:43.580 That's totally fine, not a problem there at all, 162 00:07:43.580 --> 00:07:45.580 all we're doing is modifying some data, 163 00:07:45.580 --> 00:07:48.720 passing it over to the next level, which is the TypeError. 164 00:07:48.720 --> 00:07:51.650 And at any level of our programme, at any line we want, 165 00:07:51.650 --> 00:07:54.470 we can change the data that we're passing around, 166 00:07:54.470 --> 00:07:56.340 and that's really what programming's all about 167 00:07:56.340 --> 00:08:00.493 is passing data, passing messages from one place to another. 168 00:08:02.530 --> 00:08:04.300 Anyway, now that we've looked 169 00:08:04.300 --> 00:08:06.510 at how to create your own custom errors, 170 00:08:06.510 --> 00:08:09.860 I also wanted to give you some more Python goodness, 171 00:08:09.860 --> 00:08:11.400 which is the docstring. 172 00:08:11.400 --> 00:08:13.653 We've not looked at docstrings yet, 173 00:08:14.570 --> 00:08:17.240 but, well, I'm about to tell you about them. 174 00:08:17.240 --> 00:08:22.240 Under the class and not inside the __init__ method, 175 00:08:22.470 --> 00:08:24.980 you can type a multi-line string, 176 00:08:24.980 --> 00:08:27.500 and if you remember correctly the multi-line strings 177 00:08:27.500 --> 00:08:30.400 are those that have three quotation marks at the start 178 00:08:30.400 --> 00:08:32.350 and three at the end. 179 00:08:32.350 --> 00:08:34.900 This is a multi-line string, 180 00:08:34.900 --> 00:08:36.520 which means you can, for example, 181 00:08:36.520 --> 00:08:39.850 down here print a multi-line string 182 00:08:39.850 --> 00:08:43.180 that says, "Hello How are you?", 183 00:08:46.580 --> 00:08:47.413 like so. 184 00:08:49.705 --> 00:08:50.870 And of course you cannot do that 185 00:08:50.870 --> 00:08:52.130 because you have raised an error there, 186 00:08:52.130 --> 00:08:53.670 but this is fine, you know? 187 00:08:53.670 --> 00:08:57.890 You can run this here and what you get is a bunch of lines 188 00:08:57.890 --> 00:09:02.723 there with the indentation and everything else. 189 00:09:04.290 --> 00:09:06.610 If you do that, now you get two lines. 190 00:09:06.610 --> 00:09:08.100 Of course, this is new line here, 191 00:09:08.100 --> 00:09:10.400 so you may want to do this instead. 192 00:09:10.400 --> 00:09:12.200 Now you get them all in a single line. 193 00:09:12.200 --> 00:09:14.133 This is a multi-line string, 194 00:09:15.500 --> 00:09:18.050 and multi-line string are pretty useful 195 00:09:18.050 --> 00:09:19.300 when you have a really long string 196 00:09:19.300 --> 00:09:21.720 that you want to print out or otherwise use, 197 00:09:21.720 --> 00:09:25.870 but also when you have a multi-line string 198 00:09:25.870 --> 00:09:30.870 directly underneath a class or directly underneath a method 199 00:09:31.410 --> 00:09:35.220 or a function you can actually type some stuff here 200 00:09:35.220 --> 00:09:37.793 that will be a docstring. 201 00:09:38.960 --> 00:09:41.350 That's some information about what the class does, 202 00:09:41.350 --> 00:09:43.890 or where it's used, or why it's used, 203 00:09:43.890 --> 00:09:47.410 so that other Python developers can look at it 204 00:09:47.410 --> 00:09:48.900 and understand what it does, 205 00:09:48.900 --> 00:09:51.760 and also it becomes a part of your code, 206 00:09:51.760 --> 00:09:54.120 and I'll show you exactly what that means in just a moment. 207 00:09:54.120 --> 00:09:55.610 So let's say we wanted to tell 208 00:09:55.610 --> 00:09:57.567 other developers that MyCustomError, 209 00:09:57.567 --> 00:10:02.380 "Exception raised when a specific error code is needed.", 210 00:10:02.380 --> 00:10:03.963 because this has a code here. 211 00:10:05.340 --> 00:10:07.328 And then we're gonna rename MyCustomError 212 00:10:07.328 --> 00:10:08.528 to RuntimeErrorWithCode, 213 00:10:11.622 --> 00:10:12.455 for example. 214 00:10:12.455 --> 00:10:14.200 Not a very good name, but, you know. 215 00:10:15.690 --> 00:10:17.200 So now what we can do 216 00:10:18.439 --> 00:10:21.890 is we can, whenever we're looking at this code, 217 00:10:21.890 --> 00:10:23.840 we'll quickly see, okay, this is an exception 218 00:10:23.840 --> 00:10:26.030 that's raised when a specific error code is needed. 219 00:10:26.030 --> 00:10:26.863 That's cool. 220 00:10:28.800 --> 00:10:33.800 And that helps us understand exactly what this is for. 221 00:10:34.100 --> 00:10:37.800 If you were to create an object of this type, 222 00:10:37.800 --> 00:10:42.383 without raising it, just for the sake of example, 223 00:10:44.840 --> 00:10:46.180 you can do print 224 00:10:47.520 --> 00:10:48.780 err.__doc__, 225 00:10:51.300 --> 00:10:52.350 of course we're gonna 226 00:10:55.750 --> 00:10:57.990 give it the arguments that it needs. 227 00:10:57.990 --> 00:11:00.240 So we can print the variable name, 228 00:11:00.240 --> 00:11:02.317 which is your object, .__doc__, 229 00:11:04.380 --> 00:11:06.430 and that is going to give you 230 00:11:06.430 --> 00:11:09.440 the docstring that you wrote there. 231 00:11:09.440 --> 00:11:12.530 This is particularly useful when you are developing 232 00:11:12.530 --> 00:11:17.530 and you wanna look at what something is defined to be. 233 00:11:19.150 --> 00:11:22.850 Maybe not so useful when you're writing a programme, 234 00:11:22.850 --> 00:11:24.330 but nonetheless it's interesting 235 00:11:24.330 --> 00:11:28.320 that Python sees this thing here, which is just a string, 236 00:11:28.320 --> 00:11:31.010 as something that has particular meaning. 237 00:11:31.010 --> 00:11:34.910 And using docstrings, for example in functions, 238 00:11:34.910 --> 00:11:37.330 particularly complex functions and in classes 239 00:11:37.330 --> 00:11:38.720 to explain what they do, 240 00:11:38.720 --> 00:11:41.020 and you can also use them 241 00:11:41.880 --> 00:11:45.640 at the very top of your file as a module definition, 242 00:11:45.640 --> 00:11:48.790 or what this file is all about. 243 00:11:48.790 --> 00:11:51.523 You can do that as well, you can put a docstring up here. 244 00:11:52.850 --> 00:11:57.570 There are many tools that will read those docstrings 245 00:11:57.570 --> 00:11:59.380 and create a nice page explaining 246 00:11:59.380 --> 00:12:01.940 sort of what your classes do and what your methods do 247 00:12:01.940 --> 00:12:05.170 and this is for creating documentation, 248 00:12:05.170 --> 00:12:06.180 and it can be pretty useful, 249 00:12:06.180 --> 00:12:08.590 and that's really how the docstring came to be, 250 00:12:08.590 --> 00:12:11.680 it was people wanting to add some descriptions 251 00:12:11.680 --> 00:12:14.120 on what their classes and their methods do. 252 00:12:14.120 --> 00:12:16.180 So feel free to do that, particularly if you create 253 00:12:16.180 --> 00:12:18.590 any slightly more complex functions, 254 00:12:18.590 --> 00:12:20.270 as we'll see in the following sections, 255 00:12:20.270 --> 00:12:22.840 we're gonna be actually merging all our Python knowledge 256 00:12:22.840 --> 00:12:24.840 together and creating some nicer project. 257 00:12:24.840 --> 00:12:28.200 You can use docstrings in those cases just to explain 258 00:12:28.200 --> 00:12:31.070 what exactly these things are for when you come back 259 00:12:31.070 --> 00:12:32.760 to them weeks down the line, 260 00:12:32.760 --> 00:12:34.650 or when you're working with someone else 261 00:12:34.650 --> 00:12:36.600 and you want them to be able to understand 262 00:12:36.600 --> 00:12:38.653 exactly what happened more easily. 263 00:12:39.850 --> 00:12:40.683 Okay? 264 00:12:41.610 --> 00:12:43.470 And of course, you can have your docstring, 265 00:12:43.470 --> 00:12:44.303 just as an aside, 266 00:12:44.303 --> 00:12:46.410 you can have your docstring in a single line. 267 00:12:46.410 --> 00:12:50.283 This is a single-line multi-line docstring. 268 00:12:51.150 --> 00:12:54.330 This is also fine, in case you wanna save space. 269 00:12:54.330 --> 00:12:55.870 You can have the docstring in here, 270 00:12:55.870 --> 00:12:57.560 but the docstring must have 271 00:12:57.560 --> 00:13:00.750 these triple double quotation marks. 272 00:13:00.750 --> 00:13:02.980 So these three. 273 00:13:02.980 --> 00:13:05.813 And that's just a convention for docstrings, okay? 274 00:13:06.690 --> 00:13:07.840 All right, that's it for this video. 275 00:13:07.840 --> 00:13:09.810 We talked about how to create our own errors 276 00:13:09.810 --> 00:13:12.190 by extending from a particular error, 277 00:13:12.190 --> 00:13:14.070 and if you don't want to extend from TypeError 278 00:13:14.070 --> 00:13:17.020 because your error is just not a TypeError, 279 00:13:17.020 --> 00:13:20.860 for example, you can just extend from Exception, 280 00:13:20.860 --> 00:13:22.400 sorry, not Error. 281 00:13:22.400 --> 00:13:23.840 You can extend from Exception, 282 00:13:23.840 --> 00:13:27.190 which is sort of the most base exception class 283 00:13:27.190 --> 00:13:29.170 that you should inherit from. 284 00:13:29.170 --> 00:13:32.560 Don't extend from BaseException, that's not for us to use, 285 00:13:32.560 --> 00:13:34.300 just extend from Exception. 286 00:13:34.300 --> 00:13:35.980 And that's fine. 287 00:13:35.980 --> 00:13:36.860 Okay. 288 00:13:36.860 --> 00:13:38.300 That's it for this video, again, 289 00:13:38.300 --> 00:13:40.200 and I'll see you on the very next one.