An exception is an error that occurs during the execution of a program. This article will discuss how to handle exceptions in Python programming with try-except
blocks. This is a very important construct with many applications and will help you to make your programs more robust.
If we want to handle errors gracefully in our Python programs, we can use a special block of code known as a try-except
block. First we try to run some code in the try
part of the block, and if an exception occurs, control is transferred to the except
part of the try-except
block.
Try-Except Block Example in Python
Here’s what a generic try-except
block looks like in Python:
try:
# Code that may raise an exception goes here
pass
except ExceptionType:
# Code to handle the exception goes here
pass
As you can see, the try
section contains the code that may raise an exception, and the except
section contains the code that will be executed if an exception is raised.
Surprisingly, this code actually runs without an error, even though we have used the extremely generic ExceptionType
for the except
part of the try-except
block. Not a very interesting program though. We will look at more useful examples next.
Handling Index Errors in Python
Now that we have a basic understanding of what an exception is and how try-except blocks work, let’s look at a more useful example: catching index errors in Python and handling them gracefully (i.e. without your program crashing).
This example shows how to use try
and except
to deal with when an index value error occurs.
import random
xs = [random.randint(0, 9) for _ in range(10)]
for i in range(len(xs)):
try:
print(xs[i] == xs[i + 1])
except IndexError:
print("That index doesn't exist.")
Here’s an example of output from that code:
True
False
False
False
False
False
False
False
False
That index doesn't exist.
>>>
So what’s happening in the above example?
We created a list of random numbers and displayed True
or False
depending on whether each value was the same as the next in the list. However, we were not careful about the indices we used, so we ended up testing a value at a non-existent index. However, rather than the program crashing, we anticipated the problem and provided a helpful user message instead.
Now we could have been more careful with out indices and it’s usually a good idea to anticipate these kinds of problems. However, there are some cases where the Pythonic wisdom of “EAFP, or easier to ask forgiveness than permission*” is the way to go, and for these cases, try-except
blocks are your friend.
- Sometimes!! There are some very notable exceptions to this in life outside programming.
Handling Division By Zero Errors in Python with ZeroDivisionError
Here’s another example of how you can anticpate a certain type of error and handle it gracefully in Python:
def find_mean(numbers):
try:
return sum(numbers) / len(numbers)
except ZeroDivisionError:
return 0
In this code, we define a function called find_mean
that takes a list of numbers as input. Inside the function, we use a try-except
block to catch any ZeroDivisionError
exceptions that may be raised when we try to divide the sum of the numbers by the length of the list. If a ZeroDivisionError
is raised, we return 0 from the function.
Raising Exceptions in Python
Sometimes we may want to intentionally raise an exception in out program, and then handle it appropriately. To raise an exception in Python, you use the raise
keyword. One common exception you may wish to raise is raise SystemExit
which exits your program cleanly. Raising exceptions allows us to deliberately generate the behaviour that would occur if the exception were raised by a program. For example:
raise Exception("This is an exception")
In this example, we’re raising an exception of type “Exception” with the message “This is an exception”. You can raise any type of exception you want. Some of the most important built-in exceptions in Python programming along with the errors that cause them are listed below:
Exception | Cause of Error |
---|---|
AssertionError | Raised when an assert statement fails. |
EOFError | Raised when the input() function hits end-of-file condition. |
ImportError | Raised when the imported module is not found. |
IndexError | Raised when the index of a sequence is out of range. |
KeyError | Raised when a key is not found in a dictionary. |
KeyboardInterrupt | Raised when the user hits the interrupt key (Ctrl+C or Delete). |
NameError | Raised when a variable is not found in local or global scope. |
OSError | Raised when system operation causes system related error. |
StopIteration | Raised by next() function to indicate that there is no further item to be returned by iterator. |
SyntaxError | Raised by parser when syntax error is encountered. |
IndentationError | Raised when there is incorrect indentation. |
SystemExit | Raised by sys.exit() function. |
TypeError | Raised when a function or operation is applied to an object of incorrect type. |
ValueError | Raised when a function gets an argument of correct type but improper value. |
ZeroDivisionError | Raised when the second operand of division or modulo operation is zero. |
User-defined Exceptions in Python
In Python, you can define your own exceptions by creating a class that inherits from the built-in Exception class. For example:
class MyCustomError(Exception):
pass
You can then raise this exception using the raise
keyword, like this:
raise MyCustomError("An error occurred")
You can also define your own exception class with additional attributes that can be used to store more information about the error. For example:
class MyCustomError(Exception):
def __init__(self, message, errors):
# Call the base class constructor with the parameters it needs
super().__init__(message)
# Now for your custom code...
self.errors = errors
You can then raise this exception and access the additional attributes like this:
try:
raise MyCustomError("An error occurred", [1, 2, 3])
except MyCustomError as e:
print(e.errors)
This would output [1, 2, 3]
.
There are many situations where having your own exception class is helpful, and using the above technique gives you fine control of how your program will respond to various types of error, as defined by you.
This article has discussed how to work with exceptions in Python using try-except
blocks. This can be useful for handling potential errors in your code and ensuring that your programs run smoothly.