Pythonic Ways to Handle Exceptions
Writing programs that “just” work rarely happens in practice. More often than not, you’ll need to handle exceptions—unexpected events that occur while your program is running—that have the potential to cause your program to crash. Luckily, Python provides us with the tools to elegantly handle exceptions and even use them to guide the flow of the program. This comprehensive tutorial will guide you through Python’s try/except functionality, handling different types of exceptions, custom exceptions, and exception handling best practices.

Python Exceptions: A Primer
Before delving deep into handling exceptions, it’s important to understand what an exception is. In Python, an exception is a runtime error. This means it happens while your program is executing.
Here is an example of an exception in Python:
print(10/0)
When you run the above code, Python interpreter will stop and throw a ZeroDivisionError
exception which essentially means you cannot divide a number by zero.
Python’s standard library provides a large number of built-in exceptions such as OSError
, ImportError
, IndexError
, etc that can handle a major part of your exception handling needs. However, Python also allows us to define custom exceptions for our specific needs.
Python Try/Except Block
In Python, handling exceptions is done with the use of try/except
statements.
Here’s a simple usage of a try/except
block:
try:
# try block
print(10/0)
except ZeroDivisionError:
# except block
print('You cannot divide by zero.')
```
In this example, when Python interpreter executes the code in the `try` block and encounters the `ZeroDivisionError` exception, it immediately jumps to the `except ZeroDivisionError` block and executes the code in that block, preventing the program from crashing.
## Handling Multiple Exceptions
You might need to catch and handle different types of exceptions. Here is how you can do that:
```python
try:
// code that may raise an exception
except (TypeError, ZeroDivisionError):
// handle both TypeError and ZeroDivisionError
Python also allows you to handle different exceptions differently:
try:
// code that may raise an exception
except TypeError:
// handle TypeError
except ZeroDivisionError:
// handle ZeroDivisionError
The Else Clause
Python also allows to use an else
clause in a try/except
block. The code in the else
block is executed if the code in the try
block doesn’t raise any exceptions.
try:
// code that may raise an exception
except ZeroDivisionError:
// handle ZeroDivisionError
else:
// execute if no exception was raised in the try block
The Finally Clause
Python’s try/except
statement can be used with a finally
clause as well. While the except
block executes when an exception occurs, and the else
block executes when no exceptions occur, the finally
block always executes, regardless of whether or not an exception occurred.
try:
// code that may raise an exception
except ZeroDivisionError:
// handle ZeroDivisionError
else:
// execute if no exception was raised in the try block
finally:
// always execute this block
The finally
clause is often used for cleanup actions, such as closing a file or freeing up resources.
Raising Exceptions
Sometimes, it might be necessary to raise an exception manually in your code. This is done using the raise
statement.
raise ValueError('A value error occurred.')
The Assert Statement
You can also use the assert
statement to raise exceptions in your code. The assert
statement tests if a certain condition is met. If the condition evaluates to False
, Python raises an AssertionError
exception.
assert 10 > 20, '10 is not greater than 20'
Custom Exceptions
In Python, users can define custom exceptions by creating a new class. This new class should inherit from the base Exception class.
Here is an example of creating a custom exception:
class MyCustomException(Exception):
pass
raise MyCustomException('This is a custom exception.')
Best Practices
-
Don’t Suppress Exceptions: It’s generally a bad idea to suppress all exceptions in your code. If you don’t know why an error is occurring, it’s better to let the program crash than to possibly continue running in an erratic state.
-
Use Specific Exceptions: Rather than catching all exceptions, try to catch specific exceptions that you expect might occur.
-
Provide Detailed Information: Make sure to provide as much detail as possible when handling or raising exceptions. This will help debugging if an error occurs.
-
Use Finally for Cleanup: If your code requires some cleanup that must happen even if an error occurs, put that code in the
finally
clause.
In this article, we covered how to handle exceptions in Python in an idiomatic way, including built-in exceptions provided by Python, handling multiple types of exceptions, and creating your own custom exceptions.
Remember, good exception handling is more about preventing crashes and providing detailed information when crashes do occur than it is about “catching” every possible error. Taking the time to understand and effectively handle exceptions can save you a lot of time on debugging and allows your program to reliably handle unexpected situations.
Happy Python coding!
References:
-
Python Software Foundation. “Compound statements — Python 3.9.5 Documentation.” Python Docs, https://docs.python.org/3/reference/compound_stmts.html
-
van Rossum, Guido, and Fred L. Drake. Python 3 Reference Manual. Scotts Valley, CA: CreateSpace, 2009.
-
Real Python. Python Exceptions: An Introduction https://realpython.com/python-exceptions/
-
Python Software Foundation. “Built-in Exceptions — Python 3.9.5 Documentation.” Python Docs, https://docs.python.org/3/library/exceptions.html
-
Sweigart, Al. Automate the Boring Stuff with Python, 2nd Edition: Practical Programming for Total Beginners. San Francisco, CA: No Starch Press, 2020.