Difference between revisions of "Python/Debugging"

(add some debugging notes)
 
(fix formatting)
Line 1: Line 1:
 
Debugging Python code
 
Debugging Python code
=====================
+
== Debugging Python code ==
  
 
A commonly used trick is to import the Python debugger at some point where you would like to do debugging. Just add something like this:
 
A commonly used trick is to import the Python debugger at some point where you would like to do debugging. Just add something like this:
  
{{{
+
<pre>
 
import pdb
 
import pdb
 
pdb.set_trace()
 
pdb.set_trace()
}}}
+
</pre>
  
 
and Python will drop into the Python debugger, allowing you to inspect variables, execute code, step into/next/continue, etc. The commands are pretty similar to those of gdb.
 
and Python will drop into the Python debugger, allowing you to inspect variables, execute code, step into/next/continue, etc. The commands are pretty similar to those of gdb.
  
Debugging Python extensions
+
== Debugging Python extensions ==
===========================
 
  
 
As Python extensions are written in C, it is usually not sufficient to rely on pdb when debugging extensions.  
 
As Python extensions are written in C, it is usually not sufficient to rely on pdb when debugging extensions.  
  
GDB
+
=== GDB ===
----
 
  
The following gdb macros (to be placed in ~/.gdbinit) allow you to easily inspect the reference count of python objects, their string representation as used in Python and the python stack from within gdb.
+
There are some useful gdb macros distributed with Python that allow you to easily inspect the reference count of python objects, their string representation as used in Python and the python stack from within gdb. On Debian/Ubuntu systems the file with macros can be found in /usr/share/doc/pythonX.Y/gdbinit. Copy this file to ~/.gdbinit to use it.
  
{{{
+
=== Valgrind ===
# -*- ksh -*-
 
#
 
# If you use the GNU debugger gdb to debug the Python C runtime, you
 
# might find some of the following commands useful.  Copy this to your
 
# ~/.gdbinit file and it'll get loaded into gdb automatically when you
 
# start it up.  Then, at the gdb prompt you can do things like:
 
#
 
#    (gdb) pyo apyobjectptr
 
#    <module 'foobar' (built-in)>
 
#    refcounts: 1
 
#    address    : 84a7a2c
 
#    $1 = void
 
#    (gdb)
 
 
 
# Prints a representation of the object to stderr, along with the
 
# number of reference counts it current has and the hex address the
 
# object is allocated at.  The argument must be a PyObject*
 
define pyo
 
print _PyObject_Dump($arg0)
 
end
 
 
 
# Prints a representation of the object to stderr, along with the
 
# number of reference counts it current has and the hex address the
 
# object is allocated at.  The argument must be a PyGC_Head*
 
define pyg
 
print _PyGC_Dump($arg0)
 
end
 
 
 
# print the local variables of the current frame
 
define pylocals
 
    set $_i = 0
 
    while $_i < f->f_nlocals
 
if f->f_localsplus + $_i != 0
 
    set $_names = co->co_varnames
 
    set $_name = PyString_AsString(PyTuple_GetItem($_names, $_i))
 
    printf "%s:\n", $_name
 
    # side effect of calling _PyObject_Dump is to dump the object's
 
    # info - assigning just prevents gdb from printing the
 
    # NULL return value
 
    set $_val = _PyObject_Dump(f->f_localsplus[$_i])
 
end
 
        set $_i = $_i + 1
 
    end
 
end
 
 
 
# A rewrite of the Python interpreter's line number calculator in GDB's
 
# command language
 
define lineno
 
    set $__continue = 1
 
    set $__co = f->f_code
 
    set $__lasti = f->f_lasti
 
    set $__sz = ((PyStringObject *)$__co->co_lnotab)->ob_size/2
 
    set $__p = (unsigned char *)((PyStringObject *)$__co->co_lnotab)->ob_sval
 
    set $__li = $__co->co_firstlineno
 
    set $__ad = 0
 
    while ($__sz-1 >= 0 && $__continue)
 
      set $__sz = $__sz - 1
 
      set $__ad = $__ad + *$__p
 
      set $__p = $__p + 1
 
      if ($__ad > $__lasti)
 
set $__continue = 0
 
      end
 
      set $__li = $__li + *$__p
 
      set $__p = $__p + 1
 
    end
 
    printf "%d", $__li
 
end
 
 
 
# print the current frame - verbose
 
define pyframev
 
    pyframe
 
    pylocals
 
end
 
 
 
define pyframe
 
    set $__fn = (char *)((PyStringObject *)co->co_filename)->ob_sval
 
    set $__n = (char *)((PyStringObject *)co->co_name)->ob_sval
 
    printf "%s (", $__fn
 
    lineno
 
    printf "): %s\n", $__n
 
### Uncomment these lines when using from within Emacs/XEmacs so it will
 
### automatically track/display the current Python source line
 
#    printf "%c%c%s:", 032, 032, $__fn
 
#    lineno
 
#    printf ":1\n"
 
end
 
 
 
### Use these at your own risk.  It appears that a bug in gdb causes it
 
### to crash in certain circumstances.
 
 
 
#define up
 
#    up-silently 1
 
#    printframe
 
#end
 
 
 
#define down
 
#    down-silently 1
 
#    printframe
 
#end
 
 
 
define printframe
 
    if $pc > PyEval_EvalFrameEx && $pc < PyEval_EvalCodeEx
 
pyframe
 
    else
 
        frame
 
    end
 
end
 
 
 
# Here's a somewhat fragile way to print the entire Python stack from gdb.
 
# It's fragile because the tests for the value of $pc depend on the layout
 
# of specific functions in the C source code.
 
 
 
# Explanation of while and if tests: We want to pop up the stack until we
 
# land in Py_Main (this is probably an incorrect assumption in an embedded
 
# interpreter, but the test can be extended by an interested party).  If
 
# Py_Main <= $pc <= Py_GetArgcArv is true, $pc is in Py_Main(), so the while
 
# tests succeeds as long as it's not true.  In a similar fashion the if
 
# statement tests to see if we are in PyEval_EvalFrame().
 
 
 
# print the entire Python call stack
 
define pystack
 
    while $pc < Py_Main || $pc > Py_GetArgcArgv
 
        if $pc > PyEval_EvalFrame && $pc < PyEval_EvalCodeEx
 
    pyframe
 
        end
 
        up-silently 1
 
    end
 
    select-frame 0
 
end
 
 
 
# print the entire Python call stack - verbose mode
 
define pystackv
 
    while $pc < Py_Main || $pc > Py_GetArgcArgv
 
        if $pc > PyEval_EvalFrame && $pc < PyEval_EvalCodeEx
 
    pyframev
 
        end
 
        up-silently 1
 
    end
 
    select-frame 0
 
end
 
}}}
 
 
 
Valgrind
 
--------
 
  
 
There is a suppressions file for Python's memory manager (pymalloc). It is part of the Python source tree, and distributed inside of the Python package in some distributions (Debian/Ubuntu put it in the "python" package, in /usr/lib/valgrind/python.supp). With this suppressions file enabled you *should* have no valgrind warnings from Python with any of the Samba modules loaded. See also /usr/share/doc/python2.4/README.valgrind for a more detailed explanation.
 
There is a suppressions file for Python's memory manager (pymalloc). It is part of the Python source tree, and distributed inside of the Python package in some distributions (Debian/Ubuntu put it in the "python" package, in /usr/lib/valgrind/python.supp). With this suppressions file enabled you *should* have no valgrind warnings from Python with any of the Samba modules loaded. See also /usr/share/doc/python2.4/README.valgrind for a more detailed explanation.
Line 171: Line 25:
 
Example usage:
 
Example usage:
  
{{{
+
<pre>
 
valgrind --suppressions=/usr/lib/valgrind/python.supp python foo.py
 
valgrind --suppressions=/usr/lib/valgrind/python.supp python foo.py
}}}
+
</pre>

Revision as of 20:14, 30 April 2009

Debugging Python code

Debugging Python code

A commonly used trick is to import the Python debugger at some point where you would like to do debugging. Just add something like this:

import pdb
pdb.set_trace()

and Python will drop into the Python debugger, allowing you to inspect variables, execute code, step into/next/continue, etc. The commands are pretty similar to those of gdb.

Debugging Python extensions

As Python extensions are written in C, it is usually not sufficient to rely on pdb when debugging extensions.

GDB

There are some useful gdb macros distributed with Python that allow you to easily inspect the reference count of python objects, their string representation as used in Python and the python stack from within gdb. On Debian/Ubuntu systems the file with macros can be found in /usr/share/doc/pythonX.Y/gdbinit. Copy this file to ~/.gdbinit to use it.

Valgrind

There is a suppressions file for Python's memory manager (pymalloc). It is part of the Python source tree, and distributed inside of the Python package in some distributions (Debian/Ubuntu put it in the "python" package, in /usr/lib/valgrind/python.supp). With this suppressions file enabled you *should* have no valgrind warnings from Python with any of the Samba modules loaded. See also /usr/share/doc/python2.4/README.valgrind for a more detailed explanation.

Example usage:

valgrind --suppressions=/usr/lib/valgrind/python.supp python foo.py