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()
:
# 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:
# 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:
# 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.