Department of Engineering

IT Services

python debugging

Several utilities are available to help debug your python code. Here are 3, from easiest to hardest, that you can use on CUED's linux system.

  • VSCode in the anaconda distribution has a debug menu, and some info under the "Help" menu.
  • If you have wxpython installed, you can use a debugging facility designed with wxpython in mind even if you're not using wxpython. It produces tidy output that you can easily switch on and off. Here's an example -
    from wx.tools.dbg import Logger
    dbg = Logger('mymodule')
    dbg('something to print')
    d = {1:'a', 2:'dictionary', 3:'of', 4:'words'}
    dbg(enable=1)
    
    def foo(d):
         dbg('foo', indent=1)
         bar(d)
         dbg('end of foo', indent=0)
    
    def bar(d):
         dbg('bar', indent=1)
         dbg('contents of d:', indent=1)
         l = list(d.items())
         l.sort()
         for key, value in l:
             dbg('%d =' % key, value)
         dbg(indent=0)
         dbg('end of bar', indent=0)
    
    foo(d)
        
  • If you're running Python 3.7 or newer, you can use
    breakpoint() 
    
    wherever you'd like your program to stop so that you can check values. With older Python versions, you'll need to add
    import pdb
    pdb.set_trace()
    
    to your code where you'd like the program to stop. At the prompt you can type commands interactively to check on types and values. Typing c will let the program continue. Typing n will step to the next line. See Debugging in Python for details.
  • Suppose you have a program called prog.py which is crashing (causing a segmentation fault, say). Begin the program with sys.settrace() (having imported the sys package) and do the following
  • gdb python
       run prog.py
    
    After a lot of text you'll get something like
    Program received signal SIGSEGV, Segmentation fault.
    0x00007fffef34cbad in wxWindow::AddChildGTK(wxWindow*) ()
       from /usr/local/apps/anaconda3-5.0.1/lib/python3.6/site-packages/wx/libwx_gtk3u_core-3.0.so.0
    
    If you type
       backtrace
    
    you'll see more details, though they might not help you much.

logging

The print statements used for debugging can produce a lot of output that you don't normally need. The logging package lets you disable output selectively by changing a "level" variable (an integer, so you have lots of flexibility, though there are present values like "INFO"). If you run the example below, only the "logger.info" lines will appear, but if you change the "level" variable to "DEBUG" you'll see all the output.

import logging
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format='%(asctime)s -  %(levelname)s -  %(message)s')
logger.debug('Start of program')

def factorial(n):
    logger.debug('Start of factorial(%s)'  % (n))
    logger.info('Some info')
    total = 1
    for i in range(1,n + 1):
        total *= i
        logger.debug('i is ' + str(i) + ', total is ' + str(total))
    logger.debug('End of factorial(%s)'  % (n))
    return total

print(factorial(5))
logger.debug('End of program')
  

More info is on Logging in Python: A Developer’s Guide