3 Ways to Handle KeyError Exceptions in Python

In this article let us learn

  • what KeyError exceptions are,
  • why they occur,
  • how to prevent them from occurring and
  • if they still occur then what are the crucial information we need to log for future debugging and
  • how to log this information.

In our journey to become a Proficient Python craftsman, we need to learn to design un-crashable code and this article is a step towards that goal!

If this is the first time ever seeing a python program crash, I recommend reading the article in the link below to hone your Exception Handling skills before continuing with this one.

Exceptions in Python: Everything You Need To Know!

There are 3 main ways to handle KeyError Exceptions in Python. The first 2 ways are about preventing them. We can prevent the error

  • by using the get() method
  • by using the setdefault() method

These 2 methods are provided to us by the dict class

The 3rd way is to

  • Catch them from the except and logging the information needed to debug later.

For those of you in a hurry, use the table of content below to jump to your section of interest.

Let us start by learning what KeyError means.

What is KeyError?

A dictionary is a built-in data-structure in Python used to store key-value pairs.
For example, this line of code

superDict = {'a':'aquaman', 'b':'batman'}

will create a dictionary like this

Here, the dictionary superDict is initialized with 2 key-value pairs.

Now say we wish to access the dict with a key which is not already present inside it like this

print(superDict['c']) # Expecting catwoman here!

Then python will raise a KeyError like this.

Traceback (most recent call last):

  File "<ipython-input-2-7080830d124d>", line 1, in <module>
    c = superDict['c'] # Expecting cat-woman here!

KeyError: 'c'

I am guessing you experienced something similar to this before getting here. So make sure if the key-value pair you are trying to access has been initialized properly.

To summarize, When working with dicts in Python, if we are trying to use a Key that does not match any of the keys stored inside the dict object, Python will raise a KeyError

Python provides some cool tricks to make sure our programs don’t crash if such errors occur.

To prevent KeyError Exceptions python provides us with 2 useful methods as part of the dictionary class.

  • get() method and
  • setdefault() method

Both these methods are useful in 2 different scenarios, let us see how to use them and which one to use in what scenario.

Let us first start with the get() method.

Method#1: Preventing KeyError Exceptions using the get() method

Have a look at the code below

superDict = {'a':'aquaman', 'b':'batman'}
x = superDict.get('c', 'catwoman')
print(x)

Here if the superDict does not contain the key ‘c’, the get() method will set the value for the variable x to be ‘catwoman‘ instead of throwing an exception.

Running the code above will result in the output below

catwoman

Now if we have a look at the objects created by this program, you will see that the dictionary superDict will still have only 2 key-value pairs and the variable x will contain the string ‘catwoman’ as shown below.

This can be also seen at the python prompt

>> superDict
{'a': 'aquaman', 'b': 'batman'}

>> x
'catwoman'

When to use the get() method?

If you wish to avoid KeyError Exception and avoid adding any key-value pairs to the dictionary then use the get() method.

Method#2: Preventing KeyError Exceptions using the setdefault() method

Have a look at the code below.

superDict = {'a':'aquaman', 'b':'batman'}
c = superDict.setdefault('c', 'catwoman')
d = superDict.get('d', 'duperman?!')
print(c)
print(d)

In line-2 we have used to setdefault() method to avoid KeyError and in line-3 we have used the get() method to avoid KeyError. Note that both the keys ‘c’ and ‘d’ are not available in our superDict

Let us run this code and see what happens.

catwoman
duperman?!

As you can see the code ran fine without KeyErrors!

Let us have a quick look at our dictionary superDict!

As you can see in the screenshot above, the setdefault() method has added the new key-value pair ‘c’:’catwoman’ to our superDict, and the get() method has not added anything.

When to use setdefault() method?

Use setdefault() method if you want to avoid KeyError Exception and add a key-value pair to your dictionary in the process.

Method#3: Logging important information about KeyError from the except clause

There are situations/cases where you cannot do much about preventing KeyErrors and all you can do is log the information and debug the exception later on. In such situations, we need to log the important information so that we have the clues necessary to debug this issue.

Let us see what information can we get from KeyError exceptions and how to log them.

Let us start by looking at the error message that the interpreter throws at us by manually forcing a KeyError using the raise statement.

raise KeyError

Running the line of code above leaves us with the following error message

Traceback (most recent call last):

  File "<ipython-input-1-0783d6d4a852>", line 1, in <module>
    raise KeyError

KeyError

As you can see, we are given the exact line number (line 1) and the type of exception (KeyError), both of which are crucial information to help us debug the exception later on. But if we let the python interpreter crash our program, we will not be able to log this information, also the user of our program might not enjoy the view of such a technical/scary error message.

If this is your first raise statement and you are curious to learn more about how to use this tool to enhance your python proficiency, I recommend adding the article in the link below to your reading list and read that after you finish reading this one!

Python: Manually throw/raise an Exception using the “raise” statement

Coming back to this article, let us see how to log the necessary information using try-except clauses.

import traceback

try:
  superDict = {'a':'aquaman', 'b':'batman'}
  print(superDict['c'])
except KeyError as err:
  print("Unknown key: ", err)
  traceback.print_exc()

In the code above, we have placed the problematic code in the try clause and we are using an except clause to catch KeyError exceptions. As soon as catching we are assigning the caught exception object to the variable named err and printing out the information contained inside that object using the line print(“Unknown key: “, err)

We have also imported the traceback module in Python which is used in the last line to help us understand which line of code caused the error.

Running the code above, we can see something like

Unknown key:  'c'
Traceback (most recent call last):
  File "/home/balaji/.config/spyder-py3/temp.py", line 5, in <module>
    print(superDict['c'])
KeyError: 'c'

As you can see we have printed out the error message just as we wanted!

If you look closely, there are 3 pieces of information in this error message

  1. The value inside the caught exception object (err), which is the string ‘c’, the key that caused the error!
  2. The traceback showing where in our code this exception was raised from, line-3 in this case and
  3. The exception type, which is KeyError

If you are curious to know how to control the logging of each individual piece so that you can have a tidier error log, I have an entire article dedicated to just that!
You can read that in the link below.

Python Exceptions: Getting and Handling Error Messages as strings.

And with that, I will conclude this article.

I hope you found this article useful on your journey of python mastery!

Feel free to share this article with your friends and colleagues!