How To Handle KeyError Exceptions in Python

KeyError exceptions are a common error encountered by junior Python developers.

Unfortunately, it's not always clear how to handle these exceptions.

You'll be glad to hear that handling KeyError messages is likely easier than you think. In this article, I will teach you how to handle KeyError exceptions in Python.

Table of Contents

You can skip to a specific section of this Python tutorial using the table of contents below:

What is a KeyError?

According to python's official documentation, here is the definition of a Python KeyError:

exception KeyError Raised when a mapping (dictionary) key is not found in the set of existing keys.

(You can read more here if interested: KeyError)

In simple terms, a KeyError is the result of attempting to access a key within a mapping that does not actually exist in that mapping. If you are unsure of any of those terms, let me explain.

A mapping is a data structure that maps one set of values to another, most commonly represented in Python as a dictionary. A dictionary is a specific type of mapping!

A dictionary is a data structure, available in all programming languages. We call them dict's in Python and we normally define them within a set of curly braces {}.

In a mapping (dictionary) we have sets of key-value pairs. This just means that we have a list of keys that map to values.

Think of this as the indexes in a book. The keys would be the chapters. The values would be the page number the chapter starts on.

Alternatively, think of a real-world dictionary (like Merriam-Webster's). The keys are the words. The values are the definitions of those words.

To define a dict in Python we list the sets of key-value pairs that we want to store within the mapping.

chapters_dict = {
'Chapter 1': '12',
'Chapter 2': '25',
'Chapter 3': '47'
}

A KeyError exception is raised when you try to access a key that does not actually exist inside the dict you are trying to access.

Simply put, a KeyError is a type of LookupError meaning that the error is raised when you are incorrectly looking up a value inside of a dict.

For example, if we were to try and access the key 'Chapter 5' from chapters_dict, we would raise a KeyError exception because the key does not exist within chapters_dict.

>>> chapters_dict['Chapter 5']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Chapter 5'

This means that the key you were looking for inside the dict does not exist. Therefore, you cannot access any value using that key.

Let's take a deeper look at what a dictionary is, how it's used, and when is the correct time to use them.

Return to the Table of Contents

Dictionaries in Python

A dictionary is a collection (or mapping) that is unordered, mutable, and indexed.

In Python, a dictionary is represented with the keyword dict or simple with curly braces {}. You will most often see the word dict instead of dictionary when talking about dictionaries in Python.

If you are familiar with other programming languages such as C or Java, dict's in python are equivalent to associative arrays.

It's best to think of a dict as a set of key-value pairs, where the keys must be unique and cannot be mutated after creation of the dict.

A dict by default does not keep the order of items inserted. This data structure is meant for fast lookups instead of ordering. If you need to keep a specific order in your list of items, there are better options.

The values within a dict are mutable. This means you can add/delete and update the values. Hever, you cannot update a key once it has been added to the dict. The key-value pairs are indexed to allow for fast retrieval of the value given the associated key.

Let's take a look at two examples of how you could create a dictionary object. The first example is using the dict class:

dogs = dict('Minnie': 'Corgi', 'Drogo': 'German Shepherd')

This is not the best way to create a Python dictionary. The preferred method is to use curly brackets, like this:

dogs = {
'Minnie': 'Corgi',
'Drogo': 'German Shepherd'
}

Either way is acceptable notation. However, it's generally better practice to use the curly brackets definition of a dict in Python.

Let's dig into this code to see what it actually does. This creates a dictionary structure with 2 keys (Minnie and Drogo) and 2 values (Corgi, German Shepherd). Each of the keys are associated with one of the values. If we want to get the value from the dict given a key we can do the following:

>>> dogs['Minnie'] # Asking for the value associated with the key 'Minnie'
'Corgi'

Now that you have a better understanding of python dictionaries, let's take another look at KeyError exceptions in Python.

Return to the Table of Contents

What Causes a KeyError?

As discussed earlier, a KeyError exception is raised when you attempt to get a value from a dict by looking up a key that does not exist in the data structure.

Based on the dictionary created above, if we were to run the following code the python interpreter would raise a KeyError

>>> dogs['George']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'George'

If you are unfamiliar with this Traceback information, this is a very helpful output given when any exception is raised. A Traceback can help a programmer find errors in their code.

On the last line it of the previous code block, the interpreter shows which type of exception has been raised and gives information about why the exception was raised. In this case, the exception is a KeyError and it was raised because of the key George not being found in the dict.

The Traceback also tells you which line the error has occured on, which of course is more helpful when the python code is being executed from within a .py file.

In order to avoid KeyError's in python we need to be sure of what key-value pairs have been added to the dict we are trying to read from.

Return to the Table of Contents

Avoiding KeyErrors in Python

The most effective way to avoid running into a KeyError is to be sure that you are using the correct data structure to store your data in the first place.

Two questions are helpful with this:

  • Do you need to associate values with keys in order to be able to look them up efficiently (using their keys) later?
  • Do you need to relate two pieces of data?

If you answered yes to either of these questions, you likely need to use a dict to store your data. That being said, there should be some logical way of keeping track of the keys in the dict in order to avoid a KeyError.

Normally when using a dict, we know what the keys are, that can be for two reasons.

The first reason would be if we assigned them statically. This happens when we build a dict to be used throughout our program.

If we were to create a dict to store some information about the employees we have working for our company, we could build a dictionary like so:

employees = {
'John': 'some-value',
'Steve': 'some-value',
'Jamie': 'some-value'
}

Here we are using the employee names as the keys in the dict. We should know who the employees of the company are so it would be easy to keep track of which keys exist in the structure.

The secnod reason why we generally know what a dictionary's keys are is becase we assign them dynamically, but always use the same pattern to assign the key.

An example is helpful here. Let's say we were dynamically adding to a dictionary of employees based on the employee records in our database. Every time we add to the dict we must ALWAYS use the same information as the key in order to avoid a KeyError when accessing the data inside the dictionary.

Given that our database holds an employee number for each employee of the company we could use that unique number as the key in our dict of employee data:

employees_names = {
'1001': 'John',
'1002': 'Steve',
'1003': 'Jamie'
}

This way the keys are always unique and we have an easy, logical way of keeping track of which keys actually exist.

Later, when we try to access a value in the dict we will know to use employee numbers that are stored in the database as the key in order to grab the value:

>>> employee_names['1001']
'John'

Return to the Table of Contents

Final Thoughts

In summary, KeyError Exceptions are raised by the Python interpreter when you try to access a key within a dict when that key does not exist.

A KeyError Exception is normally caused by the programmer not keeping track of the existing keys in the dict in some logical way.

The best ways to keep track of the keys in your dictionary are to:

  1. Create the dict statically, where each key is defined by you.
  2. Create the dict dynamically but always use a logical pattern to assign the keys

KeyError exceptions can be problematic, but with the knowledge gained in this tutorial you should be able to avoid them moving forward.


Written on May 7th, 2020