Key Points
- Exception handling in Python is necessary to account for possible issues that may occur during the execution of software or applications.
- There are three types of errors in Python: syntax errors, exceptions (or runtime errors), and logical errors.
- Some commonly used built-in exceptions in Python include AttributeErrors, NameErrors, TypeErrors, and IndexErrors.
- In addition to built-in exceptions, Python allows for the creation of custom exceptions to handle specific scenarios.
- Understanding exception handling is crucial for creating reliable and user-friendly software applications.
In a perfect world, all our code would work flawlessly without any need to consider what might go wrong when we put our code into production. However, we don’t live in a perfect world. As you can imagine, there are more than a few things that could go wrong during the execution of your software or application:
- A user enters the wrong type of information (maybe a string where an integer was expected)
- Usernames and/or passwords are incorrect
- The application failed to connect to the database
- Some device has failed to connect
- User has lost connection to the network or Internet
- Resources (files, database tables, etc.) are unavailable
- There is a memory conflict
- And much, much more
This doesn’t always mean there is something wrong with your code. But you will need to account for these possible issues in your code by using exceptions. If you’re new to coding with Python, you might not have had much of a chance to work with exceptions.
If that’s the case, have no fear. We’re going to dive into exception handling in Python and work our way through a few simple examples. Let’s get into it!
Exception Handling in Python: Errors vs. Exceptions
Before we dive into learning about exceptions, we need to clear something up: there is one distinct difference between an error and an exception.
You will encounter errors while coding that will prevent your software from running properly due to an issue in the syntax of your code. Meanwhile, an exception occurs during runtime.
Software developers on all levels experience errors in Python when they’re testing their code. Don’t feel bad. It is just part of the game. How you handle them is what matters.
There are three types of errors you will occasionally experience as you write your programs. Let’s look at them one by one.
Syntax Errors
This type of error occurs when the Python interpreter doesn’t understand your code. Put simply, this means you didn’t follow the syntax rules for the programming language.
For instance, if you’re printing a simple string, you might forget to put quotes around the string inside the parenthesis. You’ll receive a syntax error and will have to fix your code before it will run.
Exceptions (or Runtime Errors)
An exception occurs when something unexpected happens while your application is running. In this scenario, your syntax might be absolutely perfect, but you either misspelled something that you defined, or you encountered something unexpected once your code ran.
Logical Errors
This type of error is challenging to identify because the program will run without any error messages or exception warnings. However, it will give you incorrect results when your program runs.
This is likely due to incorrect logic written in your code. One of the ways to avoid this is to test each section of code as you go along and ensure you don’t move on until it produces the right results.
Types of Built-In Exception Handling in Python
A built-in exception is a form of runtime error built into the programming language. We don’t have enough space here to go over every single built-in exception in Python, but we will briefly discuss the most commonly used exceptions and show examples of them in code.
1. AttributeErrors
Put simply, an attribute is a variable of a class that belongs to all instances of that class. If all the appropriate attributes are used throughout your code, then you won’t have a chance to see how this works.
However, at some point, you will either misspell an attribute or forget to put a specific attribute in your class, so you’ll need to handle these possibilities in your code. See the example below.

©History-Computer.com
In this short code snippet, we’ve created an “Animal” class that has three attributes: name, age, and species. In our main code, we’ve instantiated “newAnimal,” which sends the expected parameters to the class.
Below that, we’ve created what’s called a try/except block. In the “try” portion of the block, we’re telling Python to try to execute the code within its scope.
In this block, if the code doesn’t execute successfully, Python gives control to the “except,” block, which in this example is the error message that describes exactly what went wrong. If you run this code, and the attribute isn’t typed out exactly as it is in the program, it will throw this AttributeError.
2. NameErrors
This type of built-in exception is similar to Python’s AttributeError; however, it has one slight difference. NameErrors indicate that we’re trying to access a variable or function that doesn’t exist in the current scope.
See below for an example, along with the output:

©History-Computer.com

©History-Computer.com
The code at the top is a simple function that returns the average of two numbers by dividing their sum by 2. However, you can clearly see below in the main area of our code that the call to the function is incorrect.
Since there was nothing wrong with our syntax, the compiler tried to execute the code, but it ran into a NameError because there was a mismatch between the function definition and the call to the function.
Something this simple is hard to miss when coding because you can clearly see the red underline that indicates our code is problematic. The IDE used here is PyCharm; however, any other IDE you use should behave similarly.
3. TypeErrors
This is another common exception many beginning and experienced Python developers see. It simply means Python is expecting a type that it didn’t receive.
For instance, maybe it was expecting a float value (or variable), and you coded with a string. It sounds inconceivable that this might happen, but you’ll see in the example below that it’s not hard at all to make this mistake!

©History-Computer.com
In this short program, we’re asking for input from the user of two numbers so we can do a simple calculation. However, there’s an issue if you don’t account for how Python stores input data.
You see, anything the user enters goes into memory as a string. So, if you need it in integer form, you have to cast it as an integer.
We’ve done this appropriately in the first line of the “try” block. But, in the second line, we’ve let it stay as a string to demonstrate what happens when you try to do calculations with a number stored as a string.
Since the “y” variable was stored as a string, the “try” block will give control over to the except block because it detected a TypeError exception. And you should remember that any other sort of exception would result in an error message in the terminal since it wasn’t handled within the code.
So, if we had gotten a NameError exception here (but not a TypeError), the “except” block wouldn’t execute, and the program would stop its execution, throwing a TypeError message in the terminal.
4. IndexErrors
Another common exception that occurs is when you’re working with a collection of data, and you try to access an element that doesn’t exist.
This will result in an IndexError exception, and we highly recommend always planning for this type of exception in your code when you’re working with data collections.
Here’s an example using a list in Python:

©History-Computer.com
Here, we have a list at the top of five animals. We set a boolean variable to control whether the user wants to play again, then we head into the try-except block to check for any exceptions that might occur.
If the user enters 0, 1, 2, 3, or 4 (remember: list numbering begins at 0), then one of the corresponding animals prints to the screen. However, we had to account for any numbers above that because it’s likely the user would enter bigger numbers as well.
As soon as a number bigger than 4 is entered, control goes over to the “except” block since we’ve engaged an IndexError.
From there, we let the user know what happened, and we ask them if they want to play again. If not, we switch the boolean value to True, then the program ends.
Otherwise, we loop through another time to check for a different number. Whether the “except” block executes or not, we continue asking if they want to enter another number until they finally give up and enter “n” for no.
More Built-In Exceptions
The exceptions above are not an exhaustive list of all the possible run-time errors you’ll encounter, but they are the most common. You might also want to familiarize yourself with the following built-in exceptions:
- ZeroDivisionError: Occurs when the program attempts to divide by zero
- EOFError: Occurs when you hit the end of a file without reading any data
- ImportError: Occurs when the compiler is having an issue loading a module you attempted to import
- FileNotFoundError: Occurs when a named file or directory cannot be found
- KeyError: Occurs when a key cannot be found in a dictionary
- RunTimeError: Occurs when an exception does not fit in any other category
Exception Handling in Python: User-Defined Exceptions
In addition to Python’s built-in exceptions, you also have the ability to create custom exceptions. You will find this capability to be extremely useful once you start building real-world applications that need to be able to communicate well with the end user.
The hardest part with user-defined exceptions is knowing exactly what type of exceptions you’ll need for your program. This knowledge will grow as you develop more complex algorithms and gain more experience with Python.
But, with each individual program you’re working on, you’ll be able to figure out what type of exceptions to create once you do some thorough testing of how your code behaves.
Example of a User-Defined Exception
If you want to create your own exception, you’ll need to start by defining a class that inherits from the built-in Exception class. Let’s look at how to do that.
In the example code below, we’ve created a short algorithm that tests whether a user’s email and password match the information in the database.
Before you get too excited, remember that in a real-world application, this would be much more complicated, with hashing algorithms to encrypt sensitive information and more.

©History-Computer.com
The execution with this code starts at line 17, where we create the dictionary of usernames and passwords. As you can see, each respective user has a corresponding password that our algorithm will check.
Next, we ask the user for their username and password, storing those in their own string variables. This allows us to perform the next step, where we call the “login” function that sends the username and password so we can check to see if there is a match.
In the class definition at the top of our code, we created a custom exception class, based on Python’s internal exception class. No code executes here, so we documented and used “pass” to indicate that we don’t need to do anything here.
Because we told the compiler that “InvalidLogin” is based on the “Exception” class, it knows to inherit all the elements and behavior from the original class.
Fixing the User-Defined Exception
Now, let’s look at our “login” function. It receives the username and password from the main code and checks the dictionary to see if there’s a match.
The function’s algorithm checks to see if the username exists. If it doesn’t, it raises our user-defined function, “InvalidLogin.” If it does, it moves on to check the password to make sure it’s that user’s password.
However, if both conditions pass, then the user receives a simple printed message of “Login successful,” and the program ends. Otherwise, Python raises an exception, and the user sees this message: “InvalidLogin: Invalid username or password.”
In a real-world application, you’d likely have a separate file that hosted all your exceptions to keep your main app code clean and easy to read. If that were the case here, we’d need to import the exception file at the top of the program so the compiler would know where to grab those class definitions.
Understanding Exception Handling in Python: Wrap-Up
After working through these examples and doing some testing of your own, you should now have a much better understanding of Python errors, exceptions, and how best to handle them in your code.
When it comes to creating applications meant for production, this is a concept you will need to understand backward and forward to make your software useful to a variety of users.
Just like any other type of business communication, using exceptions and exception handling will help you build a better relationship between your software product and the users who work with it daily. Now, let’s answer some commonly asked questions about exception handling in Python.
The image featured at the top of this post is ©Maria Vonotna/Shutterstock.com.