1 00:00:00,000 --> 00:00:03,200 Code that errors out is likely to kill your program. 2 00:00:03,280 --> 00:00:05,170 That's not good for the end user. 3 00:00:05,180 --> 00:00:09,240 That's not good for you as a programmer, because then someone 4 00:00:09,250 --> 00:00:11,810 else is going to complain to you, which honestly gets a little bit 5 00:00:11,820 --> 00:00:13,070 annoying after a little while. 6 00:00:13,070 --> 00:00:17,300 So we might as well catch what could be a problem and fix it beforehand. 7 00:00:17,380 --> 00:00:22,430 So luckily we have this 'try-except-finally' keywords, 8 00:00:22,440 --> 00:00:23,690 these three keywords here. 9 00:00:24,110 --> 00:00:28,380 Now, what if you're executing some code and it could error 10 00:00:28,380 --> 00:00:30,300 out for multiple reasons. 11 00:00:30,300 --> 00:00:36,720 So let's 'try: 1/0', and we could 'except' this 12 00:00:36,730 --> 00:00:44,020 'Exception as e:', and we can 'print(type(e))', and we can also 13 00:00:44,020 --> 00:00:45,700 print what the error actually is. 14 00:00:45,700 --> 00:00:50,100 Now, this is actually a really nice little, not really a hack, 15 00:00:50,100 --> 00:00:53,200 but it's a nice little way of doing things that I like to do. 16 00:00:53,200 --> 00:00:56,700 So I don't actually know all of Python's internal errors. 17 00:00:56,700 --> 00:00:59,600 There's a lot of them, and it's pretty hard for the average 18 00:00:59,600 --> 00:01:00,700 person to know all of them. 19 00:01:00,920 --> 00:01:04,280 So what I can do, is I can 'try' something, and then 'except' the 20 00:01:04,280 --> 00:01:08,000 'Exception', and if I don't know what that is, this will tell me what it is. 21 00:01:08,020 --> 00:01:09,520 So let's go ahead and run this. 22 00:01:09,530 --> 00:01:12,540 And this says, 'try: 1/0'. 23 00:01:12,540 --> 00:01:16,300 The exception was a 'class'. 24 00:01:16,370 --> 00:01:21,540 So 'e', we did 'print(type(e))'. 'class ZeroDivisionError'. 25 00:01:22,200 --> 00:01:26,400 And the error is, actually the message itself is, "division by zero". 26 00:01:26,400 --> 00:01:30,810 So now we can do this, throw 'ZeroDivisionError' in there 27 00:01:30,900 --> 00:01:37,700 and say, 'print("Cannot divide by zero")'. 28 00:01:38,900 --> 00:01:43,100 And just like that, we now have a nice way of handling this. 29 00:01:43,170 --> 00:01:45,080 So it's going to 'try' to do some code, 30 00:01:45,080 --> 00:01:46,400 the code does not work, 31 00:01:46,400 --> 00:01:50,600 we can catch this, this very specific error, and we can handle it. 32 00:01:50,600 --> 00:01:54,400 And if it's anything else, it will print what it is. 33 00:01:54,400 --> 00:01:59,200 So let's go ahead, comment this out and let's add a dictionary, 34 00:01:59,600 --> 00:02:01,600 and it's going to be a 'person'. 35 00:02:01,600 --> 00:02:04,400 And in here there's going to be, I don't know, a 'course' 36 00:02:04,400 --> 00:02:08,199 that they're enrolled in called "Python for Everybody". 37 00:02:08,199 --> 00:02:11,600 I don't know who's heard of that course, but sounds pretty 38 00:02:11,699 --> 00:02:14,800 good, doesn't it? Maybe. Bad humor. 39 00:02:14,860 --> 00:02:22,320 Anyways. We could try to say 'print(person)', and then I don't 40 00:02:22,320 --> 00:02:25,800 know their favorite food, 'fav_food', because maybe we didn't know 41 00:02:25,800 --> 00:02:27,900 that there isn't a 'fav_food' key in here. 42 00:02:27,900 --> 00:02:31,800 Let's go ahead and execute this, and we get a 'KeyError'. 43 00:02:31,800 --> 00:02:34,740 Now, this one says the dictionary key does not exist, and 44 00:02:34,740 --> 00:02:37,500 the 'KeyError' is actually the key itself. 45 00:02:37,500 --> 00:02:39,800 So now we can 'except' this as well. 46 00:02:40,100 --> 00:02:46,800 'except KeyError: print("Missing key")', and we don't know what tht is, 47 00:02:46,800 --> 00:02:48,800 so let's do 'KeyError as e:', 48 00:02:48,800 --> 00:02:51,400 [no audio] 49 00:02:51,400 --> 00:02:52,400 and let's rerun this. 50 00:02:52,420 --> 00:02:54,910 And it says "Missing key: fav_food". 51 00:02:56,100 --> 00:02:58,200 Now, that's cool that we can change these all together, but 52 00:02:58,200 --> 00:03:04,800 it's not really a realistic example, I guess of trying and catching something. 53 00:03:04,880 --> 00:03:08,250 I mean, it's sort of realistic, but let's do something else 54 00:03:08,250 --> 00:03:10,400 a little more bound to reality. 55 00:03:10,460 --> 00:03:13,280 So let's try to get some user input. 56 00:03:13,290 --> 00:03:14,600 We want two numbers. 57 00:03:14,600 --> 00:03:17,700 We want 'num1 = input( 58 00:03:18,740 --> 00:03:25,030 "Enter the first number: ", and 'num2' is going to be the 59 00:03:25,040 --> 00:03:28,930 exact same thing, but it is going to be, "Enter the second 60 00:03:29,080 --> 00:03:33,500 number: ". Now, what we're going to 'try' here? Well, we actually don't 61 00:03:33,500 --> 00:03:34,500 need to 'try' that at all. 62 00:03:34,500 --> 00:03:36,500 [no audio] 63 00:03:36,500 --> 00:03:38,700 We know that that's not going to fail on us. 64 00:03:39,500 --> 00:03:45,600 But what we want to 'try' here, is let's say casting these numbers, 65 00:03:45,650 --> 00:03:47,800 because we know these are going to come back as strings. 66 00:03:47,800 --> 00:03:51,500 So let's cast these as floats in case someone types 7.5. 67 00:03:51,500 --> 00:03:53,600 We want to be able to support that. 68 00:03:53,620 --> 00:03:58,300 So let's do 'num1 = float(num1)'. 69 00:03:58,700 --> 00:04:00,400 And let's do the same thing with 'num2'. 70 00:04:00,400 --> 00:04:02,600 [no audio] 71 00:04:02,600 --> 00:04:06,400 And let's just go ahead and throw a general exception in here 'as e' 72 00:04:06,400 --> 00:04:08,700 and so we can figure out what it is. 73 00:04:09,800 --> 00:04:15,200 We're going to 'print(type(e))', and then we're going to 'print(e)'. 74 00:04:15,200 --> 00:04:17,600 [no audio] 75 00:04:17,600 --> 00:04:19,200 Now, there could be an error in here. 76 00:04:19,200 --> 00:04:23,100 Someone could type in a string that cannot be turned into a float. 77 00:04:23,899 --> 00:04:26,800 But let's assume that it does work, and the program needs 78 00:04:26,800 --> 00:04:29,100 to continue. So we want a new total in here. 79 00:04:29,100 --> 00:04:30,800 We can say the 'total', 80 00:04:30,800 --> 00:04:32,700 actually, no, we want the division. 81 00:04:32,700 --> 00:04:37,800 So let's say 'div = num1/num2', 82 00:04:39,500 --> 00:04:40,700 and let's try this out. 83 00:04:40,700 --> 00:04:43,700 "Enter the first number: ", let's do 10, 84 00:04:43,700 --> 00:04:45,700 and the second number is going to be 20. 85 00:04:45,700 --> 00:04:50,100 And what we should have done was also printed 'div'. 86 00:04:50,500 --> 00:04:51,500 Let's try that again. 87 00:04:51,500 --> 00:04:55,700 10; 20; 10 / 20 is in fact 0.5. 88 00:04:55,730 --> 00:04:56,650 So that worked out well. 89 00:04:56,930 --> 00:05:00,600 But what if we run this again, 90 00:05:00,600 --> 00:05:04,000 and first number is 10 and someone spells out the word 20, "twenty". 91 00:05:04,000 --> 00:05:05,770 Users can be weird that way. 92 00:05:07,200 --> 00:05:09,000 We get this thing called a 'ValueError: 93 00:05:09,000 --> 00:05:11,200 could not convert the string to float'. 94 00:05:11,200 --> 00:05:14,260 So we now have one that we can 'except' in here. 95 00:05:14,260 --> 00:05:17,500 We have a particular exception that we can catch in here rather. 96 00:05:17,500 --> 00:05:20,500 So except ValueError: 97 00:05:20,900 --> 00:05:25,200 Print whatever the error is. We could print it or we just say 98 00:05:25,200 --> 00:05:29,600 "There was a value error WOOPS". 99 00:05:30,380 --> 00:05:31,520 Let's try that again. 100 00:05:31,530 --> 00:05:33,290 10, 20, 101 00:05:33,600 --> 00:05:36,800 and our program no longer errors out on us. 102 00:05:37,800 --> 00:05:40,500 What if someone says 10 and 0? 103 00:05:42,800 --> 00:05:45,000 Well, now we have a 'ZeroDivisionError'. 104 00:05:45,080 --> 00:05:46,360 We can catch that one as well. 105 00:05:46,500 --> 00:05:48,600 'except ZeroDivisionError: 106 00:05:48,600 --> 00:05:53,800 print("Cannot divide by zero")'. 107 00:05:53,890 --> 00:05:56,820 Simple as that. 10, 0, 108 00:05:57,390 --> 00:05:59,160 and it says, "Cannot divide by zero". 109 00:05:59,170 --> 00:06:02,520 So now essentially, we're on our way to creating a calculator 110 00:06:02,530 --> 00:06:04,680 program. Let's take a look at one more. 111 00:06:04,690 --> 00:06:08,450 Let's say there is a typo in here. 112 00:06:08,460 --> 00:06:11,210 Now, this is actually a bad example for a 'try-except', 113 00:06:11,210 --> 00:06:13,010 but this will show us one more error in here. 114 00:06:13,060 --> 00:06:15,550 So let's do a typo of 'num3', 115 00:06:15,560 --> 00:06:17,020 and let's say that was just a typo. 116 00:06:17,020 --> 00:06:20,500 We meant to say 'num2', but accidentally typed 'num3', that happens. 117 00:06:20,700 --> 00:06:23,800 So your first number is going to be, I don't know, 19 118 00:06:23,800 --> 00:06:25,100 The second one is going to be 56. 119 00:06:25,300 --> 00:06:26,980 And we get a 'NameError' in here. 120 00:06:26,980 --> 00:06:30,430 'num3' is not defined. So we can now go ahead and catch 121 00:06:30,500 --> 00:06:31,400 this as well. 122 00:06:32,600 --> 00:06:38,700 'print("There was an undefined variable somewhere")'. 123 00:06:39,400 --> 00:06:42,300 We could say 'as e', and put that in there. 124 00:06:42,360 --> 00:06:43,730 Let's go ahead and try this again. 125 00:06:44,900 --> 00:06:46,500 10, 34. 126 00:06:46,880 --> 00:06:48,650 "There was an undefined variable 127 00:06:48,650 --> 00:06:50,500 somewhere. name 'num3' is not defined". 128 00:06:50,540 --> 00:06:52,130 Okay, that's pretty cool. 129 00:06:52,140 --> 00:06:55,730 And this is actually a better example of something that 130 00:06:55,760 --> 00:06:58,490 is a little more likely to happen in a Python program because 131 00:06:58,500 --> 00:07:01,310 you will probably be accepting user input to some degree, 132 00:07:01,500 --> 00:07:05,100 and you need to be able to cast data. 133 00:07:05,100 --> 00:07:06,900 So we got to turn the string into a number. 134 00:07:06,900 --> 00:07:10,300 You need to be able to, maybe not check for typos necessarily, 135 00:07:10,320 --> 00:07:13,770 but maybe you don't know what those numbers are going to be, 136 00:07:13,780 --> 00:07:16,230 and if one of those numbers ends up being 0 because 137 00:07:16,240 --> 00:07:19,170 you have a malicious user, you need to be able to catch that 138 00:07:19,170 --> 00:07:20,300 'ZeroDivisionError'. 139 00:07:20,340 --> 00:07:22,920 And if it's anything else, what I like to do is just print 140 00:07:22,930 --> 00:07:25,900 the type and the error so that I can create an exception 141 00:07:25,910 --> 00:07:26,980 for it as I go along. 142 00:07:26,980 --> 00:07:29,700 Now, there's one more thing we can do in here. Two more things 143 00:07:29,720 --> 00:07:32,950 actually. We can do an 'else' statement, and we can do a 'finally' 144 00:07:32,950 --> 00:07:37,390 statement. So 'print', in an 'else' statement if there are no 145 00:07:37,390 --> 00:07:41,010 exceptions, so no exceptions were raised, 146 00:07:41,020 --> 00:07:42,360 this worked out perfectly, 147 00:07:42,360 --> 00:07:46,600 we can say, "Huzzah, success! 148 00:07:48,100 --> 00:07:54,200 We divided and ", and let's turn this 149 00:07:54,230 --> 00:07:55,570 into an f-string. 150 00:07:56,600 --> 00:07:58,700 And 'finally' will always run. 151 00:07:58,700 --> 00:08:02,900 "This will always run no matter what". 152 00:08:02,900 --> 00:08:04,900 [no audio] 153 00:08:04,900 --> 00:08:06,700 Let's try our little program here. 154 00:08:06,760 --> 00:08:07,960 Let's do 75. 155 00:08:07,960 --> 00:08:12,700 Divided by 25 is 3.0. That's correct. 156 00:08:12,700 --> 00:08:14,400 It says, "Huzzah success! 157 00:08:14,400 --> 00:08:17,100 We divided 75 by 25". 158 00:08:17,400 --> 00:08:22,200 And then the 'finally', that kicked in and said, "This will always 159 00:08:22,200 --> 00:08:24,600 run no matter what". And so a 'try- 160 00:08:24,600 --> 00:08:29,200 except-finally' block is a lot like an 'if-elif-else' statement 161 00:08:29,280 --> 00:08:31,680 but it has a slightly different purpose. 162 00:08:31,690 --> 00:08:35,190 So we're not trying to separate our code into different paths, 163 00:08:35,200 --> 00:08:38,100 which is what 'if-else' statement does. 164 00:08:38,710 --> 00:08:41,950 What we're trying to do, is perform some sort of logic, 165 00:08:41,960 --> 00:08:45,100 and if the program has a problem with that, we need to catch 166 00:08:45,110 --> 00:08:47,470 the program's error, not the user's error. 167 00:08:47,480 --> 00:08:50,710 We don't want to direct, we don't want to direct the user flow necessarily. 168 00:08:50,830 --> 00:08:54,880 We want to catch the program error, and when it errors, then 169 00:08:54,890 --> 00:08:58,260 we can sort of move the user into the right direction. 170 00:08:58,260 --> 00:09:01,400 We can make certain assumptions, or we could try things again. 171 00:09:01,460 --> 00:09:06,170 So let's go ahead and let's create a loop that will run forever 172 00:09:06,170 --> 00:09:09,700 until it can successfully divide a number. So let's do 173 00:09:09,740 --> 00:09:14,050 'while True: num1 = input()', we're just going 174 00:09:14,060 --> 00:09:17,140 to ask for number one, and 'num2' is also going to be 175 00:09:17,140 --> 00:09:18,900 input, we're going to ask for a second number. 176 00:09:18,900 --> 00:09:22,800 'num3' variable is going to be 'num1 / num2'. 177 00:09:23,900 --> 00:09:28,500 Now, this is where we would put our 'try' block because we 178 00:09:28,500 --> 00:09:30,800 know that this is likely to run into an error. 179 00:09:32,200 --> 00:09:34,900 Then we could 'except', and in that exception 180 00:09:35,100 --> 00:09:38,400 if it fails for any reason, we could say, "Nope. 181 00:09:38,800 --> 00:09:39,800 Try again". 182 00:09:39,860 --> 00:09:42,820 And let's put a 'print' statement in here. 183 00:09:42,900 --> 00:09:47,500 'print("Make a successful division")'. 184 00:09:47,500 --> 00:09:49,500 [no audio] 185 00:09:49,500 --> 00:09:50,800 Let's go ahead and run this. 186 00:09:50,800 --> 00:09:52,700 [no audio] 187 00:09:52,700 --> 00:09:53,900 It's going to ask for the first number, 188 00:09:54,000 --> 00:09:56,400 10; second number is going to be 0. 189 00:09:57,000 --> 00:09:58,000 Says, "Nope". 190 00:09:58,000 --> 00:09:59,880 Okay, going to ask for that first number again. 191 00:10:00,060 --> 00:10:01,350 10, 10. 192 00:10:02,500 --> 00:10:04,400 Nope. That's not going to work either. 193 00:10:04,480 --> 00:10:05,910 Now, why is that not working? 194 00:10:06,100 --> 00:10:09,500 Well, we said remember, this comes back to loops, 195 00:10:09,500 --> 00:10:12,400 we said, while this is True, this is always True, this will 196 00:10:12,400 --> 00:10:13,500 never, ever change. 197 00:10:13,500 --> 00:10:17,500 So because we know if this is going to cause an error, the 198 00:10:17,600 --> 00:10:20,020 code below it is not going to work in the 'try' block. It's 199 00:10:20,020 --> 00:10:24,600 going to automatically jump out, and jump into the first 'except', 200 00:10:24,600 --> 00:10:26,880 in which case we can say 'break'. 201 00:10:27,600 --> 00:10:31,200 And this cell is actually still trying to run. 202 00:10:31,220 --> 00:10:33,800 Okay. So that was just running infinitely. 203 00:10:33,800 --> 00:10:36,300 So I just went up to 'Kernel', went into 'Interrupt'. 204 00:10:36,300 --> 00:10:40,200 So what I'm going to do here is now rerun this with 'break'. 205 00:10:40,200 --> 00:10:42,200 [no audio] 206 00:10:42,200 --> 00:10:43,400 It's going to ask me for the first number, 207 00:10:43,430 --> 00:10:44,320 10; second number, 208 00:10:44,330 --> 00:10:46,520 let's do 20, and it didn't work. 209 00:10:46,530 --> 00:10:48,680 10 and 10, also not going to work. 210 00:10:48,690 --> 00:10:51,560 Now, we don't know why this is going to work, so, and this is 211 00:10:51,560 --> 00:10:54,000 starting to get, to get a little more realistic here. 212 00:10:54,020 --> 00:10:56,000 Let's go ahead and hit 'Kernel', 'Interrupt'. 213 00:10:56,010 --> 00:11:03,530 And let's 'except' this as an 'Exception as e', and 'print(e)', or 214 00:11:03,530 --> 00:11:07,800 'print(type(e))', and 'print(e)' as well. 215 00:11:07,820 --> 00:11:14,240 And all 'e' is, is a variable for 'Exception' here, and we can 216 00:11:14,250 --> 00:11:15,650 run that inside of our 'except' block. 217 00:11:15,650 --> 00:11:17,100 So let's go ahead and rerun this. 218 00:11:17,100 --> 00:11:19,900 10, 20. 'TypeError'. 219 00:11:20,900 --> 00:11:21,900 Guess what? 220 00:11:21,920 --> 00:11:25,280 You cannot divide a string by string. 221 00:11:25,500 --> 00:11:27,400 Let's go ahead. Interrupt this. 222 00:11:29,300 --> 00:11:30,600 Let's cast this as a 'float'. 223 00:11:31,300 --> 00:11:32,600 Let's cast this as a 'float'. 224 00:11:33,300 --> 00:11:34,300 Let's rerun it. 225 00:11:35,100 --> 00:11:36,100 10, 20. 226 00:11:37,300 --> 00:11:38,300 Cool. That worked. 227 00:11:38,900 --> 00:11:39,900 10, 0. 228 00:11:40,500 --> 00:11:42,700 Nope. Got a division error in there. 229 00:11:42,780 --> 00:11:44,520 Okay. Let's try that again. 230 00:11:45,000 --> 00:11:46,000 10, 1. 231 00:11:46,000 --> 00:11:47,600 And it worked, dnd then it exited. 232 00:11:47,660 --> 00:11:51,800 So that's a little more of a real life use case of 'try and 233 00:11:51,810 --> 00:11:55,660 except' in a loop that's essentially supposed to run forever 234 00:11:55,660 --> 00:11:56,800 until it's told not to. 235 00:11:57,400 --> 00:12:00,100 Anyways, that is 'try and except'. 236 00:12:00,100 --> 00:12:01,200 If you would like, 237 00:12:01,200 --> 00:12:02,400 and I would like you to, 238 00:12:02,400 --> 00:12:05,200 if you have a couple of minutes, go ahead and give this a shot. 239 00:12:05,210 --> 00:12:08,780 Create a 'try' block, cause some sort of error on purpose. 240 00:12:08,790 --> 00:12:10,610 You can even 'try: 1/0'. 241 00:12:10,610 --> 00:12:11,800 That's a common one. 242 00:12:11,800 --> 00:12:15,300 And then 'except' that particular 'exception', 243 00:12:15,900 --> 00:12:19,300 and then also run an 'else' statement and a 'finally' statement.