Python KeyError Exceptions and How to Handle Them

There are times when you have written your code but while you execute, it might not run. These types of situations occur when the input is inappropriate or you try to open a file with a wrong path or try to divide a number by zero. Due to some errors or incorrect command the output will not be displayed. This is because of errors and exceptions which are a part of the Python programming language. Learn about such concepts and gain further knowledge by joining Python Programming Course.

What is Exception Handling?

Python raises exceptions when it encounters errors during execution. A Python Exception is basically a construct that signals any important event, such as a run-time error.

Exception Handling is the process of responding to executions during computations, which often interrupts the usual flow of executing a program. It can be performed both at the software level as part of the program and also at hardware level using built-in CPU mechanisms.

Why is Exception Handling Important?

Although exceptions might be irritating when they occur, they play an essential role in high level languages by acting as a friend to the user.

An error at the time of execution might lead to two things— either your program will die or will display a blue screen of death. On the other hand, exceptions act as communication tools. It allows the program to answer the questions — what, why and how something goes wrong and then terminates the program in a delicate manner.

In simple words, exception handling protects against uncontrollable program failures and increases the potency and efficiency of your code. If you want to master yourself in programming, the knowledge of exceptions and how to handle them is very crucial, especially in Python.

What are the Errors and Exceptions in Python?

Python doesn’t like errors and exceptions and displays its dissatisfaction by terminating the program abruptly.

There are basically two types of errors in the Python language-

Type of errors in the python language

  • Syntax Error.
  • Errors occuring at run-time or Exceptions.

Syntax Errors

Syntax Errors, also known as parsing errors, occur when the parser identifies an incorrect statement. In simple words, syntax error occurs when the proper structure or syntax of the programming language is not followed.

An example of a syntax error:

>>> print( 1 / 0 ))
File "", line 1
print( 1 / 0 ))  
    ^

SyntaxError: invalid syntax

Exceptions

Exceptions occur during run-time. Python raises an exception when your code has a correct syntax but it encounters a run-time issue which it is not able to handle.

There are a number of defined built-in exceptions in Python which are used in specific situations. Some of the built-in exceptions are:

Exception Cause Of Error
ArithmeticError Raised when numerical computation fails.
FloatingPointError Raised when floating point calculation fails.
AssertionError Raised in case of failure of the Assert statement.
ZeroDivisionError Raised when division or modulo by zero takes place for all numerical values.
OverflowError Raised when result of an arithmetic operation is very large to be represented.
IndexError Raised when an index is not found in a sequence.
ImportError Raised when the imported module is not found.
IndentationError Raised when indentation is not specified properly.
KeyboardInterrupt Raised when the user hits interrupt key.
RuntimeError Raised when a generated error does not fall into any category.
SyntaxError Raised when there is an error in Python syntax.
IOError Raised when Python cannot access a file correctly on disk.
KeyError Raised when a key is not found in a dictionary.
ValueError Raised when an argument to a function is the right type but not in the right domain.
NameError Raised when an identifier is not found in the local or global namespace.
TypeError Raised when an argument to a function is not in the right type.

There are another type of built-in exceptions called warnings. They are usually issued in situations where the user is alerted of some conditions. The condition does not raise an exception; rather it  terminates the program.

What is a Python KeyError?

Before getting into KeyError, you must know the meaning of dictionary and mapping in Python.

Dictionary (dict) is an unordered collection of objects which deals with data type key. They are Python’s implementation of data structures and are also known as associative arrays. They comprise key-value pairs, in which each pair maps the key to its associated value.

Dictionary is basically a data structure that maps one set of values into another and is the most common mapping in Python.

Exception hierarchy of KeyError:

->BaseException

              ->Exception

                         ->LookupError

                                       ->KeyError

A Python KeyError is raised when you try to access an invalid key in a dictionary. In simple terms, when you see a KeyError, it denotes that the key you were looking for could not be found.

An example of KeyError:

>>> prices = { 'Pen' : 10, 'Pencil' : 5, 'Notebook' : 25}
>>> prices['Eraser']
Traceback (most recent call last):
File "<pyshell#1>", line 1, in 
prices['Eraser']
KeyError: 'Eraser'</pyshell#1>

Here, dictionary prices is declared with the prices of three items. The KeyError is raised when the item ‘Eraser’ is being accessed which is not present in prices.

Whenever an exception is raised in Python, it is done using traceback, as you can see in the example code above. It tells why an exception is raised and what caused it.

Let’s execute the same Python code from a file. This time, you will be asked to give the name of the item whose price you want to know:

# prices.py
prices = { 'Pen' : 10, 'Pencil' : 5, 'Notebook' : 25}
item = input('Get price of: ')
print(f'The price of {item} is {prices[item]}')

You will get a traceback again but you’ll also get the information about the line from which the KeyError is raised:

Get price of: Eraser
Traceback (most recent call last):
 File "prices.py", line 5, in 
  print(f'The price of {item} is {prices[item]}')
KeyError: 'Eraser'

The traceback in the example above provides the following information:

  1. A KeyError was raised.
  2. The key ‘Eraser’ was not found.
  3. The line number which raised the exception along with that line.

Where else will you find a Python KeyError?

Although most of the time, a KeyError is raised because of an invalid key in a Python dictionary or a dictionary subclass, you may also find it in other places in the Python Standard Library, such as in a zipfile. However, it denotes the same semantic meaning of the Python KeyError, which is not finding the requested key.

An example of such:

>>> from zipfile import ZipFile
>>> my_zip_file = ZipFile('Avengers.zip')
>>> my_zip_file.getinfo('Batman')
Traceback (most recent call last):
File "<pyshell#1>", line 1, in 
File "myzip.py", line 1119, in getinfo
'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'Batman' in the archive"</pyshell#1>

In this example, the zipfile.ZipFile class is used to derive information about a ZIP archive ‘Batman’ using the getinfo() function.

Here, the traceback indicates that the problem is not in your code but in the zipfile code, by showing the line which caused the problem. The exception raised here is not because of a LookUpError but rather due to the zipfile.ZipFile.getinfo()function call.

When do you need to raise a Python KeyError?

In Python Programming, it might be sensible at times to forcefully raise exceptions in your own code. You can usually raise an exception using the raise keyword and by calling the KeyError exception:

>>> raise KeyError('Batman')

Here, ‘Batman’ acts as the missing key. However, in most cases, you should provide more information about the missing key so that your next developer has a clear understanding of the problem.

Conditions to raise a Python KeyError in your code:

  • It should match the generic meaning behind the exception.
  • A message should be displayed about the missing key along with the missing key which needs to be accessed.

How to Handle a Python KeyError?

The main motive of handling a Python KeyError is to stop unexpected KeyError exceptions to be raised. There are a number of number of ways of handling a KeyError exception.

Using get()

The get()is useful in cases where the exception is raised due to a failed dictionary LookupError. It returns either the specified key value or a default value.

# prices.py
prices = { 'Pen' : 10, 'Pencil' : 5, 'Notebook' : 25}
item = input('Get price of: ')
price = prices.get(item)
if price:
  print(f'The price of {item} is {prices[item]}')
  else:
  print(f'The price of {item} is not known')

This time, you’ll not get a KeyError because the get() uses a better and safer method to retrieve the price and if not found, the default value is displayed:

Get price of: Eraser

The price of Eraser is not known

In this example, the variable price will either have the price of the item in the dictionary or the default value ( which is None by default ).

In the example above, when the key ‘Eraser’ is not found in the dictionary, the get() returns  None by default rather than raising a KeyError. You can also give another default value as a second argument by calling get():

price = prices.get(item,0)

If the key is not found, it will return 0 instead of None.

Checking for Keys

In some situations, the get() might not provide the correct information. If it returns None, it will mean that the key was not found or the value of the key in Python Dictionary is actually None, which might not be true in some cases. In such situations, you need to determine the existence of a key in the dictionary.

You can use the if and in operator to handle such cases. It checks whether a key is present in the mapping or not by returning a boolean (True or False) value:

dict = dictionary()
for i in range(50):
  key = i % 10
    if key in dict:
dict[key] += 1
else:
dict[key] = 1

In this case, we do not check what the value of the missing key is but rather we check whether the key is in the dictionary or not. This is a special way of handling an exception which is used rarely.

This technique of handling exceptions is known as Look Before You Leap(LBYL).

Using try-except

The try-except block is one of the best possible ways to handle the KeyError exceptions. It is also useful where the get() and the if and in operators are not supported.

Let’s apply the try-except block on our earlier retrieval of prices code:

# prices.py
prices = { 'Pen' : 10, 'Pencil' : 5, 'Notebook' : 25}
item = input('Get price of: ')

try:
print(f'The price of {item} is {prices[item]}')
except KeyError:
print(f'The price of {item} is not known')

Here, in this example there are two cases— normal case and a backup case. try block corresponds to the normal case and except block to the backup case. If the normal case doesn’t print the name of the item and the price and raises a KeyError, the backup case prints a different statement or a message.

Using try-except-else

This is another way of handling exceptions. The try-except-else  has three blocks— try block, except block and else block.

The else condition in a try-except statement is useful when the try condition doesn’t raise an exception. However, it must follow all the except conditions.

Let us take our previous price retrieval code to illustrate try-except-else:

# prices.py
prices = { 'Pen' : 10, 'Pencil' : 5, 'Notebook' : 25}
item = input('Get price of:')
try:
print(f'The price of {item} is {prices[item]}')
except KeyError:
print(f'The price of {item} is not known')
else:
print(f'There is no error in the statement')

First, we access an existing key in the try-except block. If the Keyerror is not raised, there are no errors. Then the else condition is executed and the statement is displayed on the screen.

Using finally

The try statement in Python can have an optional finally condition. It is used to define clean-up actions and is always executed irrespective of anything. It is generally used to release external sources.

An example to show finally:

# prices.py
prices = { 'Pen' : 10, 'Pencil' : 5, 'Notebook' : 25}
item = input('Get price of: ')
try:
print(f'The price of {item} is {prices[item]}')
except KeyError:
print(f'The price of {item} is not known')
finally:
print(f'The finally statement is executed')

Remember, the finally statement will always be executed whether an exception has occurred or not.

How to raise Custom Exceptions in Python?

Python comprises of a number of built-in exceptions which you can use in your program. However, when you’re developing your own packages, you might need to create your own custom exceptions to increase the flexibility of your program.

You can create a custom Python exception using the pre-defined class Exception:

def square(x):
if x<=0 or y<=0:
raise Exception('x should be positive')
return x * x

Here, the function square calculates the square of a number. We raise an Exception if either the input number is negative or not.

Disadvantages of Exception Handling

Though exception handling is very useful in catching and handling exceptions in Python, it also has several disadvantages. Some of which are as follows—

  • It can trap only run-time errors.
  • When you use try-except, the program will lose some performance and slow down a bit.
  • The size of the code increases when you use multiple try, except, else and finally blocks.
  • The concept of try-catch might be a little difficult to understand for beginners.
  • It is useful only in exceptional error cases.

Other than these disadvantages, understanding the concept of Exception Handling can ease your career as a programmer in the world of Python.

Conclusion

Since you have now become quite an expert in handling KeyError exceptions, you can easily debug actual errors and reduce the number of bugs in your code.

Let us sum up what we’ve learnt in the article so far:

  • Exception Handling and its importance.
  • Different types of exceptions.
  • Python KeyError
  • Finding and raising a Python KeyError.
  • Handling Python KeyError.
  • Custom Exceptions.
  • Demerits of Exception Handling.

Exceptions are considered as the tools of communication that guard you from potential damage. If you’re clear in the understanding of exceptions, they will act as a guide to your solutions.

So next time when you see a Python KeyError raised, you’ll find all the information about the location of your error and how to handle that. You will easily know how to access the key using the safer get() or the more general try-except-else blocks to control your program’s flow more efficiently and predictably.

However, if you wish to know more about errors and exceptions, you can look into the full documentation of Python Standard Library’s Errors and Exceptions and Exception Handling or register for the Python Certification Course at KnowledgeHut. You can also learn more about Python Programming in this complete Python Tutorial.

Source: knowledgehut