Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

How to Handle a Python KeyError

When you encounter a KeyError, there are a few standard ways to handle it. Depending on your use case, some of these solutions might be better than others. The ultimate goal is to stop unexpected KeyError exceptions from being raised. The usual solution is to use .get():

Python
# ages.py

ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
person = input('Get age for: ')
age = ages.get(person, 0)

if age:
    print(f'{person} is {age} years old.')
else:
    print(f"{person}'s age is unknown.")

Another solution is to check for keys. There are times when you need to determine the existence of a key in a dictionary:

Python
# parse_api_response.py
...
# Assuming you got a `response` from calling an API that might
# have an error key in the `response` if something went wrong

if 'error' in response:
    ...  # Parse the error state
else:
    ...  # Parse the success state

A more general solution is to go with try and except to isolate potential exception-raising code and provide a solution:

Python
# ages.py

ages = {'Jim': 30, 'Pam': 28, 'Kevin': 33}
person = input('Get age for: ')
print(f'{person} is {ages[person]} years old.')

00:00 When you encounter a KeyError, there are a few standard ways to handle it. Depending on your use case, some of these solutions might be better than others.

00:08 The ultimate goal is to stop unexpected KeyError exceptions from being raised. The usual solution is to use .get(). If the KeyError is raised from a failed dictionary key lookup in your own code, you can use .get() to return either the value found at the specified key or a default value. Taking the ages.py program again, you can use a better way this time to get the age from the dictionary using the key provided at the prompt. Here, line 5 shows you how you can get the age value from ages using .get().

00:41 This will result in the age variable having the age value found in the dictionary for the key provided or a default value—None, in this case.

00:51 This time, you will not get a KeyError exception raised because of the use of the safer .get() method to get the age rather than attempting to access the key directly. In this example, the KeyError is no longer raised when a bad key is provided. The key 'Michael' is not found in the dictionary, but by using .get(), we get a None returned rather than a raised KeyError.

01:13 The age variable will either have the person’s age found in the dictionary or the default value, which is None by default.

01:21 You can also specify a different default value in the .get() call by passing a second argument. You can see this in line 5 if we amend it using a different default age specified using .get().

01:34 Here, instead of 'Michael' returning None, it would return 0 because the key isn’t found and the default value to return is now 0.

01:46 Another—albeit rare—solution is to check for keys. There are times when you need to determine the existence of a key in a dictionary. In these cases, using .get() might not give you the correct information.

01:57 Getting a None returned from a call to .get() could mean that the key wasn’t found or that the value at the key in the dictionary is actually None. With a dictionary or dictionary-like object, you can use the in operator to determine whether a key is in the mapping.

02:13 This operator will return a Boolean True or False value indicating whether the key is found in the dictionary. In this example, you’re getting a response dictionary from calling an API.

02:24 This response might have an 'error' key value defined in the response, which would indicate that the response is in an error state. Here, there is a difference between checking to see if the 'error' key exists in the response and getting a default value from the key.

02:37 This is a rare case where what you’re actually looking for is if the key is in the dictionary, and not what the value at that key is.

02:46 Lastly, a more general solution is to go with try/except. As with any exception, you can always use the try/except block to isolate the potential exception-raising code and provide a backup solution.

02:58 You can use the try/except block in the ages.py program, but this time providing a default message to be printed should an error be raised in the normal case. Here, you can see the normal case in the try block of printing the person’s name and age.

03:13 The backup case is in the except block, where if a KeyError is raised in the normal case, then the backup case is to print a different message.

03:21 The try/except block solution is also a great solution for all the places that might not support .get() or the in operator. It’s also the best solution if the KeyError is being raised from another person’s code.

03:33 Here’s an example using the zipfile package again. This time, the try/except block gives us a way to stop the KeyError exception from stopping the program.

03:42 Since the ZipFile class does not provide .get() like the dictionary does, you need to use the try/except solution. In this example, you don’t have to know ahead of time what values are valid to pass to .getinfo().

Become a Member to join the conversation.