Using the debugger

When an error occurs you can start using the debugger by creating a cell with the content %debug and execute it.

Please remove this cell from the notebook once done with debugging as it breaks the marking system!

%debug

Debugger commands

This is a command prompt, you can use command in it to navigate.

  • p or print to print a variable
  • l or list to show the code
  • u or up to move up the stack
  • d or down to move down the stack
  • w or where to show the call stack
  • q or quit to quit, not optional!
  • h or help to get help

The call stack

Let’s us an example

def onlyForPositive(x):
    assert x > 0
    return 2*x
def first(x):
    a = 1
    return second(x + a )

def second(x):
    b = "Important text"
    return third(2*x)

def third(x):
    return onlyForPositive(x)

Let’s set off the trap…

first(-9)
---------------------------------------------------------------------------

AssertionError                            Traceback (most recent call last)

<ipython-input-3-507e734bd062> in <module>
----> 1 first(-9)


<ipython-input-2-67307958987f> in first(x)
      1 def first(x):
      2     a = 1
----> 3     return second(x + a )
      4 
      5 def second(x):


<ipython-input-2-67307958987f> in second(x)
      5 def second(x):
      6     b = "Important text"
----> 7     return third(2*x)
      8 
      9 def third(x):


<ipython-input-2-67307958987f> in third(x)
      8 
      9 def third(x):
---> 10     return onlyForPositive(x)


<ipython-input-1-f984f816e072> in onlyForPositive(x)
      1 def onlyForPositive(x):
----> 2     assert x > 0
      3     return 2*x


AssertionError: 

This is the call stack: a succession of functions calling each other.

Each “layer” on the stack is a function call, it is called a frame.

If you call the debugger, you get a command prompt:

You can navigate though the call trace using up and down.

You can print the call stack in the debugger using where.

You can print all variable accessible in a frame, and even execute code.

%debug
> <ipython-input-1-f984f816e072>(2)onlyForPositive()
      1 def onlyForPositive(x):
----> 2     assert x > 0
      3     return 2*x

ipdb> q

You can also decide where to call the debugger in the code, so you can be more proactive:

from IPython.core.debugger import set\_trace
def onlyForPositive(x):
    if x <= 0:
        set\_trace()
    assert x > 0
    return 2*x

You can now investigate and even fix the value of x if you want!

first(-9)
> <ipython-input-10-214f66a1f148>(4)onlyForPositive()
      1 def onlyForPositive(x):
      2     if x <= 0:
      3         set\_trace()
----> 4     assert x > 0
      5     return 2*x

ipdb> q



---------------------------------------------------------------------------

BdbQuit                                   Traceback (most recent call last)

<ipython-input-11-507e734bd062> in <module>
----> 1 first(-9)


<ipython-input-2-67307958987f> in first(x)
      1 def first(x):
      2     a = 1
----> 3     return second(x + a )
      4 
      5 def second(x):


<ipython-input-2-67307958987f> in second(x)
      5 def second(x):
      6     b = "Important text"
----> 7     return third(2*x)
      8 
      9 def third(x):


<ipython-input-2-67307958987f> in third(x)
      8 
      9 def third(x):
---> 10     return onlyForPositive(x)


<ipython-input-10-214f66a1f148> in onlyForPositive(x)
      2     if x <= 0:
      3         set\_trace()
----> 4     assert x > 0
      5     return 2*x


<ipython-input-10-214f66a1f148> in onlyForPositive(x)
      2     if x <= 0:
      3         set\_trace()
----> 4     assert x > 0
      5     return 2*x


/usr/lib64/python3.7/bdb.py in trace\_dispatch(self, frame, event, arg)
     86             return # None
     87         if event == 'line':
---> 88             return self.dispatch\_line(frame)
     89         if event == 'call':
     90             return self.dispatch\_call(frame, arg)


/usr/lib64/python3.7/bdb.py in dispatch\_line(self, frame)
    111         if self.stop\_here(frame) or self.break\_here(frame):
    112             self.user\_line(frame)
--> 113             if self.quitting: raise BdbQuit
    114         return self.trace\_dispatch
    115 


BdbQuit: 

The debugger can be turned on automatically when you encounter an error using

%pdb
Automatic pdb calling has been turned ON

Calling the same command again turns it off:

%pdb
Automatic pdb calling has been turned OFF