Inspecting the traceback

We briefly talked about the traceback in Chapter 8Testing, Profiling, and Dealing with Exceptions, when we saw several different kinds of exceptions. The traceback gives you information about what went wrong in your application. It's helpful to read it, so let's see a small example:

# traceback_simple.py
d = {'some': 'key'}
key = 'some-other'
print(d[key])

We have a dictionary and we try to access a key that isn't in it. You should remember that this will raise a KeyError exception. Let's run the code:

$ python traceback_simple.py
Traceback (most recent call last):
File "traceback_simple.py", line 3, in <module>
print(d[key])
KeyError: 'some-other'

You can see that we get all the information we need: the module name, the line that caused the error (both the number and the instruction), and the error itself. With this information, you can go back to the source code and try to understand what's going on.

Let's now create a more interesting example that builds on top of this, and exercises a feature that is only available in Python 3. Imagine that we're validating a dictionary, working on mandatory fields, therefore we expect them to be there. If not, we need to raise a custom ValidationError that we will trap further upstream in the process that runs the validator (which is not shown here, so it could be anything, really). It should be something like this:

# traceback_validator.py
class ValidatorError(Exception):
"""Raised when accessing a dict results in KeyError. """

d = {'some': 'key'}
mandatory_key = 'some-other'
try:
print(d[mandatory_key])
except KeyError as err:
raise ValidatorError(
f'`{mandatory_key}` not found in d.'
) from err

We define a custom exception that is raised when the mandatory key isn't there. Note that its body consists of its documentation string, so we don't need to add any other statements.

Very simply, we define a dummy dict and try to access it using mandatory_key. We trap KeyError and raise ValidatorError when that happens. And we do it by using the raise ... from ... syntax, which was introduced in Python 3 by PEP 3134 (https://www.python.org/dev/peps/pep-3134/), to chain exceptions. The purpose of doing this is that we may also want to raise ValidatorError in other circumstances, not necessarily as a consequence of a mandatory key being missing.

This technique allows us to run the validation in a simple try/except that only cares about ValidatorError.

Without being able to chain exceptions, we would lose information about KeyError. The code produces this result:

$ python traceback_validator.py
Traceback (most recent call last):
File "traceback_validator.py", line 7, in <module>
print(d[mandatory_key])
KeyError: 'some-other'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "traceback_validator.py", line 10, in <module>
'`{}` not found in d.'.format(mandatory_key)) from err
__main__.ValidatorError: `some-other` not found in d.

This is brilliant, because we can see the traceback of the exception that led us to raise ValidationError, as well as the traceback for the ValidationError itself.

I had a nice discussion with one of my reviewers about the traceback you get from the pip installer. His fresh Ubuntu installation was missing a few libraries that were needed by the pip packages in order to run correctly.

The reason he was blocked was that he was trying to fix the errors displayed in the traceback starting from the top one. I suggested that he started from the bottom one instead, and fix that. The reason was that, if the installer had gotten to that last line, I guess that before that, whatever error may have occurred, it was still possible to recover from it. Only after the last line, pip decided it wasn't possible to continue any further, and therefore I started fixing that one. Once the libraries required to fix that error had been installed, everything else went smoothly.

Reading a traceback can be tricky, and my friend was lacking the necessary experience to address this problem correctly. Therefore, if you end up in the same situation. Don't be discouraged, and try to shake things up a bit, don't take anything for granted.

Python has a huge and wonderful community and it's very unlikely that, when you encounter a problem, you're the first one to see it, so open a browser and search. By doing so, your searching skills will also improve because you will have to trim the error down to the minimum but essential set of details that will make your search effective.

If you want to play and understand the traceback a bit better, in the standard library there is a module you can use called, surprise surprise, traceback. It provides a standard interface to extract, format, and print stack traces of Python programs, mimicking the behavior of the Python interpreter when it prints a stack trace.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset