Exceptions in Python
This course explores the basics of exceptions in Python, including what they are, where they come from, and what their purpose is within Python.
Hello, and welcome! My name is Ben Lambert, and I’ll be your instructor for this course.
This course is part of a series of content designed to help you learn to program with the Python programming language.
Should you wish to ask me a specific question, you can do that with the contact details on screen.
You can also reach support by using the email address: firstname.lastname@example.org. And one of our cloud experts will reply.
The code that we write instructs the interpreter to perform some action. For example, binding names to objects; defining classes; calling functions, etc.
Not all of the instructions are going to be completed successfully. Sometimes an instruction results in an error. Knowing how to deal with errors in code is important for developers. In this lesson, I’ll introduce you to how Python handles errors.
There are many different reasons why errors occur.
Imagine that the code you write doesn’t follow the rules of Python’s syntax. For example, you forget the colon at the end of the function definition. In this case, the interpreter doesn’t recognize this as valid Python code.
As another example: imagine instructing Python to open a file that doesn’t exist. What should the interpreter do in this circumstance? If it’s told to open a file, and the file doesn’t exist - it can’t complete the instruction.
These two examples describe two different types of error. The first is a syntax error. These occur when the interpreter reads a line of code that doesn’t follow Python’s syntax rules.
This type of error is extremely common. Especially as you’re first learning. When these errors occur the runtime immediately displays an error and provides details about where the error occurred in the code.
The other type of error occurs when an exception is raised in code. In the example with the file, we asked the interpreter to open a file which doesn’t exist.
This causes the interpreter to raise an exception. Python calls these types of errors exceptions. Because when these errors occur they’re exceptions to the expected code-flow.
Syntax errors are a normal part of writing code. Whenever we explore new code and new language features, we’ll experience syntax errors. As our muscle memory forms we see fewer of these. So we’re not going to focus too much on these.
The only thing worth knowing about syntax errors is that they’re telling you that the code does not follow Python’s language rules. They attempt to get you as close to the error as possible by providing a line number where the error occurred. However, these line numbers are not one hundred percent accurate.
When you encounter syntax errors double-check each line around the line specified in the error. It’s often to the smallest detail. A missing colon. Not following standard indentation. Missing a closing bracket or comma. Every new developer will spend time trying to figure out these types of errors. Do your best to be patient with these errors and check your syntax carefully.
Our primary focus in this lesson will be exceptions. When a syntax error occurs the interpreter displays the error and stops running. The way to recover from this is to fix the code and restart it. Exceptions are different because Python provides a mechanism to recover from them.
Exceptions are just Python objects. They typically contain details about the reason for the exception. Including line numbers, error messages, and other useful details which can help when debugging.
Python’s language syntax provides rules for instructing the runtime to raise an exception. That’s the term Python uses when referring to producing an exception, which is why the keyword used to raise an exception is: raise.
Python includes different types of Exception objects. For example, the FileNotFoundError is an exception object which will be raised if the runtime can’t find a requested file.
Exceptions are used to denote that the expected flow of code cannot happen for some reason. There are many different reasons why code may raise an exception. Some of those reasons will result in our code flowing into an unrecoverable state.
For example: if our code relies on a file that doesn’t exist then our code has nothing to do.
However, there are many cases where we can safely recover from an exception. For example: imagine that we want to attempt to download some configuration file. When dealing with external input such as from a network, failures are possible. You could lose internet access; the file could be missing; etc...
In a case such as this, maybe it’s okay to use a default configuration if one can’t be downloaded. In this use case, we can recover from the exception.
Python provides syntax rules for detecting and handling exceptions.
Allow me to introduce the try-family of keywords. Which includes the keyword try, except, and finally.
When we have code which might raise an exception we run that code inside a try block.
This try keyword tells the interpreter that we’re about to try to run some code that we know might raise an exception.
This except keyword tells the interpreter that if the try block raises a FileNotFoundError then it should run the except code block.
This finally keyword tells the interpreter that when it’s done with running the try and or except blocks that it must run this last no matter if an exception was raised or not.
There are some rules regarding the except and finally keywords.
When we use a try-block it must have either an except or finally-block. And, we can specify multiple except blocks.
By specifying multiple we check for different types of exceptions. Imagine that the block of code we want to try might result in a few possible exceptions, we could handle each one with its own except block.
However, we could also consolidate them into a single generic exception.
The except syntax starts with the keyword except and ends with a colon and new line. In between is where we can specify the exceptions that this except block should handle.
We can leave the exception blank and catch all exceptions. We can specify one, or we can specify multiple by placing them in a tuple.
The syntax for finally is just the word finally followed by a colon and new line.
Since exceptions are just objects we can interact with their attributes and methods.
There’s a specific syntax used to bind a name to an exception block. Inside the except definition after the exceptions to check for we can bind a name to an exception which enables us to use that name inside the except block.
For example: by binding the name err to this FileNotFoundError object we can access the filename attribute allowing us to display the name of the missing file.
So, using the try-family of keywords you’re able to attempt to run some code which may raise an exception. Then we can handle the exception using except and or finally blocks.
Let’s talk more about raising exceptions. Whenever your code cannot complete its intended purpose, you should consider raising an exception.
To raise an exception we specify the keyword raise followed by an exception object.
This example raises a generic exception with an included error message. This Exception here is just a built-in class which includes an input parameter to specify the error message.
When creating your own code you can raise built-in exceptions or you can create custom exceptions.
Custom exceptions allow you to define the required attributes and methods.
Custom exceptions are quite useful for certain applications. However, for smaller or in-house applications, the built-in exceptions are also viable.
Custom exceptions are created by creating a new class which inherits from an existing exception. We don’t get into the details now. However, just know that you can create custom exceptions should your use case call for it.
Okay, this seems like a natural stopping point. Here are your key takeaways for this lesson.
- Exceptions are used to denote that the expected flow of code cannot happen for some reason.
- Two types of exceptions are syntax errors and runtime exceptions.
- Syntax errors result in the application stopping.
- Runtime exceptions can be detected and handled.
- Exceptions are handled using the try-family of keywords including:
- We can raise exceptions using the raise keyword followed by an exception object.
That's all for this lesson. Thanks so much for watching. And I’ll see you in another lesson!
Ben Lambert is a software engineer and was previously the lead author for DevOps and Microsoft Azure training content at Cloud Academy. His courses and learning paths covered Cloud Ecosystem technologies such as DC/OS, configuration management tools, and containers. As a software engineer, Ben’s experience includes building highly available web and mobile apps. When he’s not building software, he’s hiking, camping, or creating video games.