Handling Exceptions

Learn how to handle exceptions in Python.

try..except block

Let’s look at the tail side of the exception coin. If we encounter an exception situation, how should our code react to or recover from it? We handle exceptions by wrapping any code that might throw one (whether it is exception code itself, or a call to any function that may have an exception raised) inside a try...except clause.

Handle an exception

If we run this simple script below using our existing never_returns() function—which, as we know very well, always throws an exception—we get the following output:

Press + to interact
from typing import NoReturn
def never_returns() -> NoReturn:
print("I am about to raise an exception")
raise Exception("This is always raised")
print("This line will never execute")
return "I won't be returned"
def handler() -> None:
try:
never_returns()
print("Never executed")
except Exception as ex:
print(f"I caught an exception: {ex!r}")
print("Executed after the exception")
handler()

The never_returns() function happily informs us that it is about to raise an exception and raises it. The handler() function’s except clause catches the exception. Once caught, we are able to clean up after ourselves (in this case, by outputting that we are handling the situation), and continue on our way. The remainder of the code in the never_returns() function remains unexecuted, but the code in the handler() function after the try: statement is able to recover and continue.

Note: The indentation around try and except. The try clause wraps any code that might throw an exception. The except clause is then back on the same indentation level as the try line. Any code to handle the exception is indented inside the except clause. Then normal code resumes at the original indentation level.

The problem with the preceding code is that it uses the Exception class to match any type of exception. What if we were writing some code that could raise either TypeError or ZeroDivisionError? We might need to catch ZeroDivisionError because it reflects a known object state, but let any other exceptions propagate to the console because they reflect bugs we need to catch and kill.

Here’s a rather silly function that does just that: ...