Lesson 37:

Using the Debugger

A debugger allows you to run a program line by line, in order to debug it at various stages.

NB: The ipdb module does not seem to play well in Jupyter, and may occasionally require a kernal restart.

In iPython, the ipdb module holds an interactive debugging tool that acts similarly to the IDLE editor used in the book.

It is started with idpb.set_trace(), and can take various arguments in the interactive prompt to provide information.

ipdb (iPython Debugger) Commands:

  • the n(next) continues program execution to to the next line in the code.
  • the s(step) steps to the next line, whether its in the code or in the function itself (i.e. instead print() or input() here.
  • the c(continue) command continues until another breakpoint.
  • The l(list) will list a larger portion of the code.
  • The p(print) or pp(pretty print) will print an argument.
  • The a(arguments) will return the current arguments.
  • The j(jump) command jumps to a line of code, skipping any other lines.
  • The q(quit) command quits the iPython debugger.
  • The ?(help) shows all available commands.

Use Cases:

  • pp locals() to pretty print local variables (requires pprint module.)
  • pp globals() to pretty print global variables.
  • Change variables while the program is running by editing the locals() on the fly; step back and forward through the code with n and j.

Simple Adding Program:


In [3]:
def simpleAdd(): 
    print('Enter the first nuber to add:')
    first = input()
    print('Enter the second number to add:')
    second = input()
    print('Enter the third number to add:')
    third = input()
    print('The sum is ' + first + second + third +'.')
simpleAdd()


Enter the first nuber to add:
1
Enter the second number to add:
2
Enter the third number to add:
3
The sum is 123.

This code produces an incorrent response. The debugger can be used to go through the program line by line and find the errors.


In [20]:
import ipdb # Import the iPython debugger

def simpleAdd(): 
    ipdb.set_trace() # Invoke the iPython debugger
    print('Enter the first nuber to add:')
    first = input()
    print('Enter the second number to add:')
    second = input()
    print('Enter the third number to add:')
    third = input()
    print('The sum is ' + first + second + third +'.')
simpleAdd()


> <ipython-input-20-3c0c4cfab90a>(5)simpleAdd()
      4     ipdb.set_trace() # Invoke the iPython debugger
----> 5     print('Enter the first nuber to add:')
      6     first = input()

ipdb> n
Enter the first nuber to add:
> <ipython-input-20-3c0c4cfab90a>(6)simpleAdd()
      5     print('Enter the first nuber to add:')
----> 6     first = input()
      7     print('Enter the second number to add:')

ipdb> n
1
> <ipython-input-20-3c0c4cfab90a>(7)simpleAdd()
      6     first = input()
----> 7     print('Enter the second number to add:')
      8     second = input()

ipdb> help

Documented commands (type help <topic>):
========================================
EOF    c          d        h         next    pp       retval  u          whatis
a      cl         debug    help      p       psource  run     unalias    where 
alias  clear      disable  ignore    pdef    q        rv      undisplay
args   commands   display  interact  pdoc    quit     s       unt      
b      condition  down     j         pfile   r        source  until    
break  cont       enable   jump      pinfo   restart  step    up       
bt     continue   exit     n         pinfo2  return   tbreak  w        

Miscellaneous help topics:
==========================
pdb  exec

Undocumented commands:
======================
l  list  ll  longlist

ipdb> pp locals()
{'first': '1'}
ipdb> whatis first
<class 'str'>
ipdb> quit
---------------------------------------------------------------------------
BdbQuit                                   Traceback (most recent call last)
<ipython-input-20-3c0c4cfab90a> in <module>()
     10     third = input()
     11     print('The sum is ' + first + second + third +'.')
---> 12 simpleAdd()

<ipython-input-20-3c0c4cfab90a> in simpleAdd()
      5     print('Enter the first nuber to add:')
      6     first = input()
----> 7     print('Enter the second number to add:')
      8     second = input()
      9     print('Enter the third number to add:')

<ipython-input-20-3c0c4cfab90a> in simpleAdd()
      5     print('Enter the first nuber to add:')
      6     first = input()
----> 7     print('Enter the second number to add:')
      8     second = input()
      9     print('Enter the third number to add:')

/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/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)

/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/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: 

The problem with the program was that input() stores its responses as 'strings', and therefore concatenates as a string, not an integer. Assing an int() fixes this problem:


In [19]:
#import ipdb # Import the iPython debugger

def simpleAdd(): 
    #ipdb.set_trace() # Invoke the iPython debugger
    print('Enter the first number to add:')
    first = int(input())
    print('Enter the second number to add:')
    second = int(input())
    print('Enter the third number to add:')
    third = int(input())
    print('The sum is ' + str(first + second + third) +'.')
simpleAdd()


Enter the first number to add:
1
Enter the second number to add:
2
Enter the third number to add:
3
The sum is 6.

Stepping(s) into the next step of the program is more than just going to the next (n) or continuing (c) the program.

It actually goes into the code of the function being called at that line.


In [2]:
def blah():
    print('blah')
    print('blah')
    print('blah')
    moreblah()
    print('blah')
    print('blah')
    print('blah')
    evenmoreblah()
    

def moreblah():
    print('more blah')
    print('more blah')
    print('more blah')
    evenmoreblah()

    
def evenmoreblah(): 
    print('even more blah')
    
print(blah())


blah
blah
blah
more blah
more blah
more blah
even more blah
blah
blah
blah
even more blah
None

Tracing the function gains the following output:


In [4]:
import ipdb # Import iPython Debugger

def blah():
    ipdb.set_trace() # Invoke the iPython debugger
    print('blah')
    print('blah')
    print('blah')
    moreblah()
    print('blah')
    print('blah')
    print('blah')
    evenmoreblah()
    

def moreblah():
    print('more blah')
    print('more blah')
    print('more blah')
    evenmoreblah()

    
def evenmoreblah(): 
    print('even more blah')
    
print(blah())


> <ipython-input-4-4a417a62b379>(5)blah()
      4     ipdb.set_trace() # Invoke the iPython debugger
----> 5     print('blah')
      6     print('blah')

ipdb> n
blah
> <ipython-input-4-4a417a62b379>(6)blah()
      5     print('blah')
----> 6     print('blah')
      7     print('blah')

ipdb> n
blah
> <ipython-input-4-4a417a62b379>(7)blah()
      6     print('blah')
----> 7     print('blah')
      8     moreblah()

ipdb> n
blah
> <ipython-input-4-4a417a62b379>(8)blah()
      7     print('blah')
----> 8     moreblah()
      9     print('blah')

ipdb> s
--Call--
> <ipython-input-4-4a417a62b379>(15)moreblah()
     14 
---> 15 def moreblah():
     16     print('more blah')

ipdb> n
> <ipython-input-4-4a417a62b379>(16)moreblah()
     15 def moreblah():
---> 16     print('more blah')
     17     print('more blah')

ipdb> n
more blah
> <ipython-input-4-4a417a62b379>(17)moreblah()
     16     print('more blah')
---> 17     print('more blah')
     18     print('more blah')

ipdb> n
more blah
> <ipython-input-4-4a417a62b379>(18)moreblah()
     17     print('more blah')
---> 18     print('more blah')
     19     evenmoreblah()

ipdb> n
more blah
> <ipython-input-4-4a417a62b379>(19)moreblah()
     18     print('more blah')
---> 19     evenmoreblah()
     20 

ipdb> s
--Call--
> <ipython-input-4-4a417a62b379>(22)evenmoreblah()
     21 
---> 22 def evenmoreblah():
     23     print('even more blah')

ipdb> q
---------------------------------------------------------------------------
BdbQuit                                   Traceback (most recent call last)
<ipython-input-4-4a417a62b379> in <module>()
     23     print('even more blah')
     24 
---> 25 print(blah())

<ipython-input-4-4a417a62b379> in blah()
      6     print('blah')
      7     print('blah')
----> 8     moreblah()
      9     print('blah')
     10     print('blah')

<ipython-input-4-4a417a62b379> in moreblah()
     17     print('more blah')
     18     print('more blah')
---> 19     evenmoreblah()
     20 
     21 

<ipython-input-4-4a417a62b379> in evenmoreblah()
     20 
     21 
---> 22 def evenmoreblah():
     23     print('even more blah')
     24 

/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/bdb.py in trace_dispatch(self, frame, event, arg)
     48             return self.dispatch_line(frame)
     49         if event == 'call':
---> 50             return self.dispatch_call(frame, arg)
     51         if event == 'return':
     52             return self.dispatch_return(frame, arg)

/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/bdb.py in dispatch_call(self, frame, arg)
     81             return self.trace_dispatch
     82         self.user_call(frame, arg)
---> 83         if self.quitting: raise BdbQuit
     84         return self.trace_dispatch
     85 

BdbQuit: 

Stepping is useful, but can be really slow.

One way to let the program run normally until a an issue, i.e. breakpoints.

Coin Flip Program:


In [8]:
import random

heads = 0

for i in range(1,1001):
    if random.randint(0, 1) == 1:
        heads = heads + 1
    if i == 500:
        print('Halfway done!')
        
print('Heads came up ' + str(heads) + ' times.')


Halfway done!
Heads came up 507 times.

Factorial Program

Create a program that can return the n! of a number (5! = 1 * 2 * 3 * 4 * 5 = 120).


In [ ]:
import ipdb # Import iPython Debugger


import random

heads = 0

for i in range(1,1001):
    ipdb.set_trace() # Invoke the iPython debugger
    if random.randint(0, 1) == 1:
        heads = heads + 1
    if i == 500:
        print('Halfway done!')
        
print('Heads came up ' + str(heads) + ' times.')


> <ipython-input-9-e2ce77f9158d>(10)<module>()
      9     ipdb.set_trace() # Invoke the iPython debugger
---> 10     if random.randint(0, 1) == 1:
     11         heads = heads + 1

ipdb> c
> <ipython-input-9-e2ce77f9158d>(9)<module>()
      8 for i in range(1,1001):
----> 9     ipdb.set_trace() # Invoke the iPython debugger
     10     if random.randint(0, 1) == 1:

ipdb> c
> <ipython-input-9-e2ce77f9158d>(10)<module>()
      9     ipdb.set_trace() # Invoke the iPython debugger
---> 10     if random.randint(0, 1) == 1:
     11         heads = heads + 1

ipdb> pp locals()
{'In': ['',
        'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
        'import ipdb # Import iPython Debugger\n'
        '\n'
        '\n'
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')"],
 'Out': {},
 '_': '',
 '__': '',
 '___': '',
 '__builtin__': <module 'builtins' (built-in)>,
 '__builtins__': <module 'builtins' (built-in)>,
 '__doc__': 'Automatically created module for IPython interactive environment',
 '__loader__': None,
 '__name__': '__main__',
 '__package__': None,
 '__spec__': None,
 '_dh': ['/Users/vivek.menon/Dropbox/learn/books/python/AutomateTheBoringStuffWithPython'],
 '_i': 'import random\n'
       '\n'
       'heads = 0\n'
       '\n'
       'for i in range(1,1001):\n'
       '    if random.randint(0, 1) == 1:\n'
       '        heads = heads + 1\n'
       '    if i == 500:\n'
       "        print('Halfway done!')\n"
       '        \n'
       "print('Heads came up ' + str(heads) + ' times.')",
 '_i1': 'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i2': 'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i3': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i4': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i5': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i6': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i7': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
 '_i8': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
 '_i9': 'import ipdb # Import iPython Debugger\n'
        '\n'
        '\n'
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
 '_ih': ['',
         'def blah():\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'def blah():\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up' + str(heads) + ' times.')",
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up ' + str(heads) + ' times.')",
         'import ipdb # Import iPython Debugger\n'
         '\n'
         '\n'
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up ' + str(heads) + ' times.')"],
 '_ii': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
 '_iii': 'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
 '_oh': {},
 '_sh': <module 'IPython.core.shadowns' from '/usr/local/lib/python3.5/site-packages/IPython/core/shadowns.py'>,
 'blah': <function blah at 0x11141e1e0>,
 'evenmoreblah': <function evenmoreblah at 0x1113b27b8>,
 'exit': <IPython.core.autocall.ZMQExitAutocall object at 0x110875e80>,
 'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x110095d68>>,
 'heads': 2,
 'i': 3,
 'ipdb': <module 'ipdb' from '/usr/local/lib/python3.5/site-packages/ipdb/__init__.py'>,
 'moreblah': <function moreblah at 0x1113b2bf8>,
 'quit': <IPython.core.autocall.ZMQExitAutocall object at 0x110875e80>,
 'random': <module 'random' from '/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/random.py'>}
ipdb> pp globals()
{'In': ['',
        'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
        'import ipdb # Import iPython Debugger\n'
        '\n'
        '\n'
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')"],
 'Out': {},
 '_': '',
 '__': '',
 '___': '',
 '__builtin__': <module 'builtins' (built-in)>,
 '__builtins__': <module 'builtins' (built-in)>,
 '__doc__': 'Automatically created module for IPython interactive environment',
 '__loader__': None,
 '__name__': '__main__',
 '__package__': None,
 '__spec__': None,
 '_dh': ['/Users/vivek.menon/Dropbox/learn/books/python/AutomateTheBoringStuffWithPython'],
 '_i': 'import random\n'
       '\n'
       'heads = 0\n'
       '\n'
       'for i in range(1,1001):\n'
       '    if random.randint(0, 1) == 1:\n'
       '        heads = heads + 1\n'
       '    if i == 500:\n'
       "        print('Halfway done!')\n"
       '        \n'
       "print('Heads came up ' + str(heads) + ' times.')",
 '_i1': 'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i2': 'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i3': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i4': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i5': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i6': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i7': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
 '_i8': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
 '_i9': 'import ipdb # Import iPython Debugger\n'
        '\n'
        '\n'
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
 '_ih': ['',
         'def blah():\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'def blah():\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up' + str(heads) + ' times.')",
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up ' + str(heads) + ' times.')",
         'import ipdb # Import iPython Debugger\n'
         '\n'
         '\n'
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up ' + str(heads) + ' times.')"],
 '_ii': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
 '_iii': 'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
 '_oh': {},
 '_sh': <module 'IPython.core.shadowns' from '/usr/local/lib/python3.5/site-packages/IPython/core/shadowns.py'>,
 'blah': <function blah at 0x11141e1e0>,
 'evenmoreblah': <function evenmoreblah at 0x1113b27b8>,
 'exit': <IPython.core.autocall.ZMQExitAutocall object at 0x110875e80>,
 'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x110095d68>>,
 'heads': 2,
 'i': 3,
 'ipdb': <module 'ipdb' from '/usr/local/lib/python3.5/site-packages/ipdb/__init__.py'>,
 'moreblah': <function moreblah at 0x1113b2bf8>,
 'quit': <IPython.core.autocall.ZMQExitAutocall object at 0x110875e80>,
 'random': <module 'random' from '/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/random.py'>}
ipdb> pp locals()
{'In': ['',
        'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
        'import ipdb # Import iPython Debugger\n'
        '\n'
        '\n'
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')"],
 'Out': {},
 '_': '',
 '__': '',
 '___': '',
 '__builtin__': <module 'builtins' (built-in)>,
 '__builtins__': <module 'builtins' (built-in)>,
 '__doc__': 'Automatically created module for IPython interactive environment',
 '__loader__': None,
 '__name__': '__main__',
 '__package__': None,
 '__spec__': None,
 '_dh': ['/Users/vivek.menon/Dropbox/learn/books/python/AutomateTheBoringStuffWithPython'],
 '_i': 'import random\n'
       '\n'
       'heads = 0\n'
       '\n'
       'for i in range(1,1001):\n'
       '    if random.randint(0, 1) == 1:\n'
       '        heads = heads + 1\n'
       '    if i == 500:\n'
       "        print('Halfway done!')\n"
       '        \n'
       "print('Heads came up ' + str(heads) + ' times.')",
 '_i1': 'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i2': 'def blah():\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i3': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i4': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i5': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i6': 'import ipdb # Import iPython Debugger\n'
        '\n'
        'def blah():\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    moreblah()\n'
        "    print('blah')\n"
        "    print('blah')\n"
        "    print('blah')\n"
        '    evenmoreblah()\n'
        '    \n'
        '\n'
        'def moreblah():\n'
        "    print('more blah')\n"
        "    print('more blah')\n"
        "    print('more blah')\n"
        '    evenmoreblah()\n'
        '\n'
        '    \n'
        'def evenmoreblah(): \n'
        "    print('even more blah')\n"
        '    \n'
        'print(blah())',
 '_i7': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
 '_i8': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
 '_i9': 'import ipdb # Import iPython Debugger\n'
        '\n'
        '\n'
        'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    ipdb.set_trace() # Invoke the iPython debugger\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up ' + str(heads) + ' times.')",
 '_ih': ['',
         'def blah():\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'def blah():\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up' + str(heads) + ' times.')",
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up ' + str(heads) + ' times.')",
         'import ipdb # Import iPython Debugger\n'
         '\n'
         '\n'
         'import random\n'
         '\n'
         'heads = 0\n'
         '\n'
         'for i in range(1,1001):\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         '    if random.randint(0, 1) == 1:\n'
         '        heads = heads + 1\n'
         '    if i == 500:\n'
         "        print('Halfway done!')\n"
         '        \n'
         "print('Heads came up ' + str(heads) + ' times.')"],
 '_ii': 'import random\n'
        '\n'
        'heads = 0\n'
        '\n'
        'for i in range(1,1001):\n'
        '    if random.randint(0, 1) == 1:\n'
        '        heads = heads + 1\n'
        '    if i == 500:\n'
        "        print('Halfway done!')\n"
        '        \n'
        "print('Heads came up' + str(heads) + ' times.')",
 '_iii': 'import ipdb # Import iPython Debugger\n'
         '\n'
         'def blah():\n'
         '    ipdb.set_trace() # Invoke the iPython debugger\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    moreblah()\n'
         "    print('blah')\n"
         "    print('blah')\n"
         "    print('blah')\n"
         '    evenmoreblah()\n'
         '    \n'
         '\n'
         'def moreblah():\n'
         "    print('more blah')\n"
         "    print('more blah')\n"
         "    print('more blah')\n"
         '    evenmoreblah()\n'
         '\n'
         '    \n'
         'def evenmoreblah(): \n'
         "    print('even more blah')\n"
         '    \n'
         'print(blah())',
 '_oh': {},
 '_sh': <module 'IPython.core.shadowns' from '/usr/local/lib/python3.5/site-packages/IPython/core/shadowns.py'>,
 'blah': <function blah at 0x11141e1e0>,
 'evenmoreblah': <function evenmoreblah at 0x1113b27b8>,
 'exit': <IPython.core.autocall.ZMQExitAutocall object at 0x110875e80>,
 'get_ipython': <bound method InteractiveShell.get_ipython of <ipykernel.zmqshell.ZMQInteractiveShell object at 0x110095d68>>,
 'heads': 2,
 'i': 3,
 'ipdb': <module 'ipdb' from '/usr/local/lib/python3.5/site-packages/ipdb/__init__.py'>,
 'moreblah': <function moreblah at 0x1113b2bf8>,
 'quit': <IPython.core.autocall.ZMQExitAutocall object at 0x110875e80>,
 'random': <module 'random' from '/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/random.py'>}
ipdb> i
3
ipdb> c
> <ipython-input-9-e2ce77f9158d>(9)<module>()
      8 for i in range(1,1001):
----> 9     ipdb.set_trace() # Invoke the iPython debugger
     10     if random.randint(0, 1) == 1:

ipdb> i
4
ipdb> c
> <ipython-input-9-e2ce77f9158d>(10)<module>()
      9     ipdb.set_trace() # Invoke the iPython debugger
---> 10     if random.randint(0, 1) == 1:
     11         heads = heads + 1

ipdb> i
5

Using continue(c) runs through every iteration, which means debugging this code would take a lot of work, since we'd have to go through every trial.

A faster option is merely to step right into the first if statement using the until(un) command.

Once at that point, you can also use the break('b') to set a breakpoint there for future jumping.

This continues the program until a new line is reached, i.e. by finishing the loop:


In [5]:
import ipdb # Import iPython Debugger


import random

heads = 0

for i in range(1,1001):
    ipdb.set_trace() # Invoke the iPython debugger
    if random.randint(0, 1) == 1:
        heads = heads + 1
    if i == 500:
        print('Halfway done!')
        
print('Heads came up ' + str(heads) + ' times.')


> <ipython-input-5-e2ce77f9158d>(10)<module>()
      9     ipdb.set_trace() # Invoke the iPython debugger
---> 10     if random.randint(0, 1) == 1:
     11         heads = heads + 1

ipdb> unt
> <ipython-input-5-e2ce77f9158d>(11)<module>()
     10     if random.randint(0, 1) == 1:
---> 11         heads = heads + 1
     12     if i == 500:

ipdb> unt
> <ipython-input-5-e2ce77f9158d>(12)<module>()
     11         heads = heads + 1
---> 12     if i == 500:
     13         print('Halfway done!')

ipdb> b
ipdb> q
---------------------------------------------------------------------------
BdbQuit                                   Traceback (most recent call last)
<ipython-input-5-e2ce77f9158d> in <module>()
     10     if random.randint(0, 1) == 1:
     11         heads = heads + 1
---> 12     if i == 500:
     13         print('Halfway done!')
     14 

<ipython-input-5-e2ce77f9158d> in <module>()
     10     if random.randint(0, 1) == 1:
     11         heads = heads + 1
---> 12     if i == 500:
     13         print('Halfway done!')
     14 

/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/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)

/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/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: 

Recap

  • The debugger is a tool that lets you execute Python code one line at a time and shows you the values in variables.
  • The debugger in iPython is called through the ipdb module and invoked with ipdb.set_trace() in afunction.
  • It takes the following commands:
  • the n(next) continues program execution to to the next line in the code.
  • the s(step) steps to the next line, whether its in the code or in the function itself (i.e. instead print() or input() here.
  • the c(continue) command continues until another breakpoint.
  • The l(list) will list a larger portion of the code.
  • The p(print) or pp(pretty print) will print an argument.
  • The a(arguments) will return the current arguments.
  • The j(jump) command jumps to a line of code, skipping any other lines.
  • The q(quit) command quits the iPython debugger.
  • The ?(help) shows all available commands.