Chapter 9: Exception handling

Exception instances

face Josiah Wang

I will keep this last chapter short.

We will talk a bit more about Exceptions.

If you have noticed, all Exceptions are classes. This includes the more specific Exceptions like KeyError, ZeroDivisionError or ModuleNotFoundError. When an error occurs, Python actually creates an instance of the appropriate Exception class.

You can actually call the constructor of an Exception like creating a normal object. You can pass as many custom input arguments to the constructor as needed.

>>> error = IndexError("a", "b", "c")

All Exceptions have an .args attribute (which is a tuple). They store the arguments which you passed to the constructor earlier. You can also print() an exception which will print out the string representation of the arguments.

>>> error.args
('a', 'b', 'c')
>>> print(error)
('a', 'b', 'c')

The power of being able to pass custom arguments come when you need to purposely **raise** an exception (that is, cause an exception). Here, you can pass any custom message you want.

>>> raise KeyError("I cannot find the key!", "This occurred in line 5", "The value of key is 5")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: ('I cannot find the key!', 'This occurred in line 5', 'The value of key is 5')

If an exception occurs inside a try block, you can actually obtain the instance of the exception with the as keyword inside your except clause. You can then process the arguments, use it for debugging, reformat the error to display to the user, or even re-raise the exception for the caller (or Python) to handle!

try:
    raise KeyError("I cannot find the key!", "This occurred in line 5", "The value of key is 5")
except KeyError as error: 
    args = error.args
    print(type(args))
    print(args[0])
    print(args[1])
    print(args[2])
    print(error)
    raise Exception(f"An error occurred. Here is the message {args[0]}")