February 23, 2020 will

Better Python tracebacks with Rich

One of my goals in writing Rich was to render really nice Python tracebacks. And now that feature has landed.

I've never found Python tracebacks to be a great debugging aid beyond telling me what the exception was, and where it occurred. In a recent update to Rich, I've tried to refresh the humble traceback to give enough context to diagnose errors before switching back to the editor.

Here's an example of a rich traceback:

Rich traceback on OSX

There is highlighting to help pick out filename, line, and function, etc. There's also a snippet of code for each stack frame, with line numbers and syntax highlighting. It's configurable, but I find that 7 lines of code are enough to make it relatable to the file in my editor, and give me a better understanding of the context that lead to the exception.

Here's how tracebacks render on Windows:

Rich traceback on Windows terminal

For reference, here's the same traceback rendered in a more traditional way:

Just a regular old traceback

To try out rich tracebacks, install the exception handler as follows:

from rich.traceback import install
install()

Now any uncaught exceptions will rendered by Rich. See the docs for details.

Rich is quite usable as a library now, but is still in active development. If you have any ideas on how to improve rich tracebacks or any other aspect of the library, let me know.

Use Markdown for formatting
*Italic* **Bold** `inline code` Links to [Google](http://www.google.com) > This is a quote > ```python import this ```
your comment will be previewed here
gravatar
Jim

The likelihood of install() clashing with something else is quite high. Why don't you suggest the following instead?

import rich.traceback
rich.traceback.install()
gravatar
Will McGugan

Fair point. I would hope that most developers would know how to handle a namespace clash like that.

gravatar
André Roberge

Very, nice! In fact, your entire "rich" project is beautiful.

Two possible (subjective) improvements:

  1. Add info about local variable values found where the exception was raised.
  2. Perhaps give an option to limit the traceback to only show the first and last frame in the exception stack?

I do both of these in Friendly-traceback (https://aroberge.github.io/friendly-traceback-docs/docs/html/) aimed at a difference audience. My tracebacks do not look nearly as nice as yours!

gravatar
Will McGugan

Thanks André.

I have thought about annotations for local variables. I might tackle that at some point.

I was also thinking about rendering a few more lines for the last stack frame, and maybe less lines for framework and stdlib.

Your friendly tracebacks looks like a fantastic resource for beginners. Maybe I can borrow some of your ideas.

gravatar
miao ming

Could I apply the exception output to logger? like logger.error(stackprinter.format())

gravatar
Will McGugan

You could, although it wouldn't be a one liner at the moment.

I could implement it, but I don't think the logging library would handle color and styles well, and the traceback would end up being in monochrome -- still useful, just not as pretty.

gravatar
Lars Alexander Blumberg

Great tool. We use pytest a lot. Does it also improve pytest's traceback output for failing tests?

gravatar
Will McGugan

Not currently, although I'm sure its possible. I'm still working towards a Rich 1.0, I'm hoping that somebody else will attempt to integrate it with pytest in the meantime.