Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Debugging

Code always eventually breaks. Let’s look at some broken code:

from typing import Tuple
import sys
def broken() -> None:
    1 / 0
def my_broken_function() -> Tuple[int, int]:
    x = 6
    y = 4
    x += 2
    y *= 2
    x -= y
    y /= x
    return x, y
my_broken_function()
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[5], line 1
----> 1 my_broken_function()

Cell In[4], line 7, in my_broken_function()
      5 y *= 2
      6 x -= y
----> 7 y /= x
      8 return x, y

ZeroDivisionError: division by zero

IPython debugger

Try writing %debug into the cell below! (you can even skip the %)

%debug

The mini-language here is pdb, and is similar to gdb and many other debuggers. You can step forward, up, etc. You can set breakpoints, or you can just write breakpoint() anywhere, and the “current” debugger will pick up there!

Rich tracebacks

Another trick comes from the Rich library. You can install a nicer traceback handler. Never do this in a library, but only in applications and user code.

import rich.traceback

rich.traceback.install(show_locals=True)
<bound method InteractiveShell.excepthook of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x7f97708a0d70>>

This needs to be in a file (normally it will be) for the traceback to show up nicely:

%%writefile tmp_rich.py
def my_broken_function():
    x = 6
    y = 4
    x += 2
    y *= 2
    x -= y
    y /= x
    return x, y
Writing tmp_rich.py
import tmp_rich

tmp_rich.my_broken_function()
Loading...

Debugging in Jupyter Lab

This used to require the Xeus Python kernel instead of IPython, but IPyKernel 6+ now supports the visual debugger protocol directly.

Turn on the debugger with the switch on the top right. Click on the line numbers to set a breakpoint. Then run.

def my_broken_function():
    # breakpoint()
    x = 6
    y = 4
    x += 2
    y *= 2
    x -= y
    y /= x
    return x, y
my_broken_function()
Loading...