Debugging Hints

AMath 586, Spring Quarter 2019 at the University of Washington. For other notebooks, see Index.ipynb or the [Index of all notebooks on Github].

(https://github.com/rjleveque/amath586s2019/blob/master/notebooks/Index.ipynb). The Python pdb module is useful for debugging Python code.

This notebook shows a simple example.

In [2]:
%matplotlib inline
In [3]:
from pylab import *
from scipy.linalg import expm

The code below is supposed to solve $u'(t) = Iu(t)$ with $u(0) = \eta$ in the $5\times 5$ case where $I$ is the identity matrix and all elements of $\eta$ are equal to 1.

In [4]:
def utrue(t):
    # Solve u'(t) = A u(t) with A = I, u(0) = eta
    A = eye(5)   # 5x5 identity matrix
    eta = array([1.,1.,1.,1.])
    u = dot(expm(A*t),eta)
    return u
In [5]:
utrue(1.)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-5-e870a834c014> in <module>()
----> 1 utrue(1.)

<ipython-input-4-84243fc44f8b> in utrue(t)
      3     A = eye(5)   # 5x5 identity matrix
      4     eta = array([1.,1.,1.,1.])
----> 5     u = dot(expm(A*t),eta)
      6     return u

ValueError: shapes (5,5) and (4,) not aligned: 5 (dim 1) != 4 (dim 0)

The error message above some information about where the error occurred.

We can get more information by turning on the pdb debugger, using the Jupyter "magic" command pdb. If you execute this a second time, it turns the debugger off.

In [6]:
pdb
Automatic pdb calling has been turned ON
In [7]:
utrue(1.)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-e870a834c014> in <module>()
----> 1 utrue(1.)

<ipython-input-4-84243fc44f8b> in utrue(t)
      3     A = eye(5)   # 5x5 identity matrix
      4     eta = array([1.,1.,1.,1.])
----> 5     u = dot(expm(A*t),eta)
      6     return u

ValueError: shapes (5,5) and (4,) not aligned: 5 (dim 1) != 4 (dim 0)
> <ipython-input-4-84243fc44f8b>(5)utrue()
      2     # Solve u'(t) = A u(t) with A = I, u(0) = eta
      3     A = eye(5)   # 5x5 identity matrix
      4     eta = array([1.,1.,1.,1.])
----> 5     u = dot(expm(A*t),eta)
      6     return u

ipdb> A.shape
(5, 5)
ipdb> t.shape
*** AttributeError: 'float' object has no attribute 'shape'
ipdb> eta.shape
(4,)
ipdb> eta
array([1., 1., 1., 1.])
ipdb> A
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])
ipdb> print(A)
[[1. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 1.]]
ipdb> q

Note that it now gives a ipdb> prompt at the point where the exception occurred. You can query the state of variable, e.g. by typing an expresssion or a print statement and then hitting Enter. Type q and Enter to quit (which you have to do before you can execute any other cell).

In [8]:
pdb
Automatic pdb calling has been turned OFF

You can also put in a breakpoint to probe the state at some point, even if it is not giving an error. Here's a corrected version of the code with a breakpoint added.

In [11]:
from pdb import set_trace

def utrue(t):
    # Solve u'(t) = A u(t) with A = I, u(0) = eta
    A = eye(5)   # 5x5 identity matrix
    eta = array([1.,1.,1.,1.,1.])
    u = dot(expm(A*t),eta)
    print('This breakpoint is after setting A, eta, and u')
    set_trace()  # breakpoint here
    return u
In [13]:
utrue(1.)
This breakpoint is after setting A, eta, and u
> <ipython-input-11-41e99edc18f7>(10)utrue()
-> return u
(Pdb) print('A = \n',A)
A = 
 [[1. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0.]
 [0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 1.]]
(Pdb) print('eta = ',eta)
eta =  [1. 1. 1. 1. 1.]
(Pdb) q
---------------------------------------------------------------------------
BdbQuit                                   Traceback (most recent call last)
<ipython-input-13-e870a834c014> in <module>()
----> 1 utrue(1.)

<ipython-input-11-41e99edc18f7> in utrue(t)
      8     print('This breakpoint is after setting A, eta, and u')
      9     set_trace()  # breakpoint here
---> 10     return u

<ipython-input-11-41e99edc18f7> in utrue(t)
      8     print('This breakpoint is after setting A, eta, and u')
      9     set_trace()  # breakpoint here
---> 10     return u

~/miniconda/envs/geo/lib/python3.6/bdb.py in trace_dispatch(self, frame, event, arg)
     46             return # None
     47         if event == 'line':
---> 48             return self.dispatch_line(frame)
     49         if event == 'call':
     50             return self.dispatch_call(frame, arg)

~/miniconda/envs/geo/lib/python3.6/bdb.py in dispatch_line(self, frame)
     65         if self.stop_here(frame) or self.break_here(frame):
     66             self.user_line(frame)
---> 67             if self.quitting: raise BdbQuit
     68         return self.trace_dispatch
     69 

BdbQuit: 

You can end the (Pdb) prompt with q to quit, or if things are working right, with c to continue executing from this point.

If you happen to delete a cell when it's waiting for pdb input and the notebook hangs, remember that you can select Interrupt from the Kernel menu.

In [ ]: