Transcript from the "Tracebacks & Exceptions" Lesson
>> A little bit about tracebacks. We talked about how to read the traceback from a Python program earlier in the day, that we wanna start at the bottom and go up to the top. If we have any uncaught exceptions in our program, it is going to exit the program.
[00:00:20] So let's make a new file called exceptions.py. And run this, and we will see that end of the program never printed out. Because this through an exception, I'm trying to ask Python to convert the letter A into an integer and it's like, I don't know what you're talking about.
[00:00:48] So you need to be mindful that your programs don't have any uncaught exceptions or they will behave in unpredictable ways. You want to catch your exceptions with syntax called try and accept. And let's look at what that looks like. Try is a keyword with a colon and you need to indent the code that you are trying one level.
[00:01:19] And then, The accept keyword. And following the accept keyword, this will work, Without any additional arguments. I can say an exception happened. So if I run this, it will print out an exception happened and then end of the program. Generally, we want to catch exceptions that are specific as possible.
[00:01:57] And for the most part, Python gives us a helpful hint. What was the exception here? Well, it was a value error. I tried to pass in a string into the integer. So I can just copy this class and paste it after the accept. And that will catch the very specific exception that was thrown in this case.
[00:02:23] If I had another exception in here like a divide by zero. No, that's also a value error. It's another good exception. Let's say I have a dictionary and I tried to get a key that is not in that dictionary that will error. Is that also value error? Yeah, right, I would need to change the order of these.
[00:03:03] So because this threw an exception first, it's getting caught here. I wanna show you something else. This will throw a key error. And so now if I run this, I will see my key error. That's because this is the code that threw the exception. If I change this back to just accept with no specific exception, it's going to catch both of them.
[00:03:30] Generally, this is a bad thing. You want to be as specific about catching your exceptions as possible so that when you need to go back and figure out and debug and troubleshoot what went wrong. You have a pretty clear idea about which code caught which exception. Now, you can also have different code run for different exceptions.
[00:03:53] So I can say accept value error, say, a value exception happened. And then I can say accept key error, which I got the class from right here and print out, A key was not found. And now because this was first, I got my key error first. If I switch the order of these, I will get my value error first.
[00:04:26] But now I have both scenarios covered. And I know exactly which exception was thrown and where. I'm not going to deep dive into exceptions, but I think they're a pretty important fundamental concept of Python. So I recommend that you go back through and take a look at this detailed chapter.
[00:04:50] Most importantly, you never want to catch exceptions that aren't specific. If you try to catch from the exception that all exceptions inherit from, you could end up with a program that doesn't let you exit it with Ctrl+C or other weird and subtle bugs. So make sure that you have a pretty good understanding of how exceptions work.
[00:05:24] There's also a finally clause that you can include that is an optional block, that will run after the try regardless of if an exception was thrown or not. So if you need to do some cleanup, that's the right place for it. So let's chat about the exception hierarchy.
[00:05:44] Python has a lot of useful built-in exceptions that you are probably going to encounter. You can find a detailed list of those built-in exceptions in the Python documentation. An important thing to know about exceptions is, like everything else in Python, are just objects. So they follow an inheritance hierarchy, and more specific classes inherit from more general ones.
[00:06:11] For example, the zero division error is a subclass of arithmetic error, which is a subclass of exception, which is a subclass of base exception. That's why the best practice is to catch more specific exceptions first. And don't catch exception and especially don't catch base exception. If you catch base exception, you're gonna swallow every type of exception, including the one that is thrown when you press Ctrl+C while a Python program is running.
[00:06:47] And that is the keyboard interrupt exception. If you catch base exception, it will cause your Python program not to respond to Ctrl+C, which is not something that anybody wants. So don't do it. Because exceptions are regular classes, we can also inherit from them from our own custom exceptions.
[00:07:09] Which makes it very easy to make our own custom specific exceptions. This makes our programs a lot more readable. And I'm not going to cover custom exceptions here, but there are custom exceptions that you can work through in practice.