Part 4 of 6 · Chapter 1 of 4

When Things Go Wrong on Purpose

A traceback looks like the program's way of failing at you. Read one from the bottom up instead of the top down, and it turns into the most specific bug report you will ever get for free.

Intermediate9 min read

A traceback looks like the program's way of failing at you. Read one from the bottom up instead of the top down, and it turns into the most specific bug report you will ever get for free.

Reading a traceback from the bottom, not the top

The last line of a traceback names the exception and the message — that is what actually went wrong. The lines above it, read bottom to top, are the chain of calls that led there: the line your own code was on comes first, then whatever called that, and so on outward.

Read the traceback from the bottom up
report.py
scores = [88, 92, 79]print(scores[3])
Traceback
$ Traceback (most recent call last):  File "report.py", line 2, in <module>    print(scores[3])          ~~~~~~^^^$ IndexError: list index out of range

Catching the error you expect, not every error

try and except let a program recover from an error instead of crashing — but only if you catch the specific exception you actually anticipated.

Terminal
$ >>> try:$ ...     price = prices["mango"]$ ... except KeyError:$ ...     price = 0$ ...$ >>> price$ 0

Raising one on purpose, before it happens by accident

You can trigger an exception deliberately with raise, which is often clearer than letting bad input travel deep into a program before it fails on its own, somewhere confusing.

Terminal
$ >>> def set_age(age):$ ...     if age < 0:$ ...         raise ValueError("age cannot be negative")$ ...     return age$ ...$ >>> set_age(-5)$ ValueError: age cannot be negative

Failing loudly and immediately, at the exact line where the impossible value appeared, is far easier to debug than a program that accepts -5 quietly and produces a nonsensical answer four functions later.

Key takeaways

  • Read a traceback's last line first — it names the actual exception and message.
  • try/except recovers from an error you anticipated. Name the specific exception; never write a bare except:.
  • A bare except: also swallows errors you did not anticipate, hiding real bugs instead of surfacing them.
  • raise a specific exception the moment you detect an impossible value, rather than letting it travel further into the program.