Write Pythonic Code Like a Seasoned Developer Transcripts
Chapter: Methods and Functions
Lecture: I'm going to ignore your return value
0:01 In programming, there is several philosophies on how you deal with errors.
0:04 One hand you could look at all the various cases,
0:08 check all the return values and do a lot of tests before you take any action,
0:12 to try your best to make sure that action will be successful.
0:15 This type of error handling is popular in languages
0:18 that are not great at supporting exceptions, such as C.
0:22 Languages that do support exceptions lean more towards
0:25 what you might consider an optimistic style of API
0:28 where they try things and if something goes wrong
0:30 they will catch the errors and deal with it.
0:32 So let's look at how this shows up in Python.
0:36 All right, so we have this little support file and in here it has a couple of things,
0:40 support module, it has a download file and if you attempt to download a file
0:45 you need a bunch of things to line up in your favor,
0:48 you need the network to be connected,
0:50 you need the download url to in theory be set,
0:53 you need the dns to be active, and you need to actually have access
0:55 to the file you are trying to download.
0:58 Over here, we can just say well let's just try to download this file
1:01 and see what we get, let's run it.
1:03 Oh, cool, we download some data and it was a binary array saying cool,
1:07 but what if something goes wrong, let's go over here and fiddle with it,
1:10 like let's say, let's turn off the network,
1:13 now how is this going to work if we run.
1:16 Not so amazing, "connection reset error, cannot connect to the network",
1:21 oh, ok well, if we were coming from a C language,
1:27 a C style language or these languages that typically
1:30 don't have great exception support,
1:33 even if they do have exception support often it's not well used
1:36 as an idiomatic way of programming, think C++ for example,
1:39 you will see lots of people write algorithms that look like this,
1:43 we'll say oh we've got to make sure the network is working
1:46 so we'll say if s.check network,
1:50 maybe we'll at least put some guarding clause
1:52 so we don't have that nested thing we spoke about earlier,
1:55 so we'll print out something like "cannot download, no network".
2:01 And we'll just bale, so let's run this again, excellent, ok.
2:05 So, "cannot download, no network",
2:07 we didn't crush we just caught this error,
2:10 now there is some other cases we should check,
2:13 we can check the dns, we can also check the url.
2:19 Ok, still network is turn off, let's go turn that back on,
2:25 it will turn off the let's see the dns now, oh "can't download no dns",
2:31 so here is the question, if I look at this code,
2:33 is this code going to deal with all the possible errors,
2:37 well, it turns out in several ways no, no it's not,
2:41 so first of all we forgot to check this one, say that's true,
2:46 so we thought we did all the tests it looks like we did a lot of tests at least,
2:50 we are running and crash, still no go,
2:53 because we don't have permission to that file and it turns out
2:55 if we are doing real network io deep down within Python
2:58 there is all sorts of exceptions that can be raised,
3:01 so the message, the takeaways basically even if you try to write this code
3:05 they still deal with all the cases you need to put this into a try except block.
3:09 Ok, well if you are going to go and put into a try except block,
3:12 why don't you just skip all of this stuff,
3:15 use the programming model that's called
3:17 "it's easier to ask for forgiveness than permission",
3:20 try it, if it fails we'll say well, sorry catch handle the error
3:23 because it's kind of the code we are going to have to write anyway,
3:26 so let's write a better version, a more Pythonic version here,
3:30 so we are going to say run with checks and let's first turn everything back on,
3:33 so this download works, so down here we have run with error handling,
3:37 it's going to crash, well, if I had an error with crash,
3:41 because we have no error handling,
3:43 so let's go over here and we'll put a try except block,
3:46 so we'll say we want to catch exception and maybe even get the details like so,
3:50 and we'll print "cannot download" something like this.
3:58 So, let's go ahead and run it, remember the download is working right now,
4:02 so this will just do the same thing, perfect, it does, let's go mess with this,
4:06 let's go say turn off the network, and run it.
4:10 "Cannot download, connection reset error", "cannot connect the network",
4:15 ok, that's not great, let's put this back on but it didn't crash, we did catch it,
4:20 that's cool, let's say go over here to the permission one
4:23 "cannot download permission error", "cannot access resource permission denied".
4:27 This is cool, this is much more Pythonic than what we have above here, right,
4:31 one thing we are not doing is we are not doing anything different based on errors,
4:35 now technically we are displaying a message that varies by error to the user
4:39 but often you can do different things based on the type of vary you've got.
4:43 We might want to deal with dns and network errors differently
4:47 than we would deal with say a permission issue
4:50 which also might be dealt with differently
4:52 than if we had like the download url not set.
4:55 So let's go down here and write this last version,
5:01 so let's just see the types of errors we get,
5:03 so I can get a permission error, maybe I want to run some particular code
5:08 if there is a permission error so we could say add another except block here
5:11 permission error as pe and then I could we don't even necessarily need the details,
5:15 we just need the time, so we could print something like
5:18 "cannot download you don't have permission".
5:23 Theoretically, you would do something different here
5:26 we also saw that there was a connection errors,
5:30 here like so we can print "cannot download, problem with network";
5:36 and maybe we could put the details in here like this,
5:43 "cannot download you don't have permission",
5:45 so excellent, this code is running, now if we have a different type of error,
5:49 say there is a problem with the network
5:53 "cannot download, problem with network, cannot connect".
5:57 What about dns- "problem with network, no dns".
6:02 So there are two Pythonic takeaways here,
6:04 one this is how you do error handling in Python,
6:08 much less like this although there are places
6:11 where this makes sense it's not the primary way of doing it.
6:14 And if you are creating APIs don't depend on the return value and lots of checks,
6:20 instead just try do evaporation and raise errors properly,
6:24 make sure that you raise different types of errors
6:26 so that we can do different types of responses based on those errors.
6:31 So here is what you call a "look before you leap style of programming",
6:36 it's popular in C and C++ and those types of languages,
6:40 you do a bunch of checks, and you try tot est every possible case
6:43 and then you perform the operation and hopefully
6:46 you have tested everything you need to and it doesn't just crash on you right.
6:49 In Python, we typically don't write code like this,
6:52 instead, we write code like this, we just assume that it's going to work
6:56 so we'll just do the most cleanest, simplest, straightforward way of downloading file,
7:01 how do you want to do that, s.download file, boom, done,
7:04 but, something goes wrong, we put it into try except block,
7:07 handle the error and we can even use different error types
7:10 most specific to most general, to deal with specific errors,
7:13 like for example here we are dealing with the class of network errors
7:17 that have to do with dns and basic network connectivity.
7:21 This is called
7:23 "it's easier to ask for forgiveness than permission style of programming".
7:27 And this is more Pythonic than the prior version.