Python Debugging Techniques
aymanh.com
aymanh.com
Is there a way to attach a python shell to a running process? I saw something similar for ruby but could not find a python equivalent.
Here is how I launch a shell for my projects (it tries to use IPython, if it isn't working it uses code.interact): http://paste.plurk.com/show/17110/
There are also macros for gdb floating around -- you can attach the gdb (C etc.) debugger to a python process and then examine the stack through some gdb macros, but the interactivity is limited (unless perhaps someone has built it up more). That lets you break in at any moment. See http://wiki.python.org/moin/DebuggingWithGdb
In many cases where a production process is doing mysterious things, using strace or perhaps ltrace on it can give a good hint to what it is doing, together with lsof to see what files it's reading/writing.
http://github.com/cool-RR/PythonTurtle/
Check out the directory "/src/shelltoprocess".
It's a package for connecting a GUI shell, running on wxPython, to a Python process spawned by the multiprocessing package. It's documented and MIT-licensed.
* Finding and fixing memory leaks in Python's WSGI applications: http://amix.dk/blog/viewEntry/19420
This is a more general technique on debugging memory leaks using objgraph.py (that can be used in non-WSGI applications):
* Tracing Python memory leaks: http://www.lshift.net/blog/2008/11/14/tracing-python-memory-...
Debugging python in a server environment is a different kettle of fish though, I keep running in to situation where something goes wrong under water and there is absolutely no hint of where the problem lies. That's one of the most frustrating bits of django/python development as far as I can see.
In PHP it is a very rare occurence to get an error that does not immediately pinpoint the problem spot. In django/python if you get an error message at all chances are that it will send you off on an hour+ tour of the documentation trying to figure out what is up.
For fun have an alternate_name on a foreign key that ends on _id, you will get errors that have absolutely no bearing on the location of the problem.
http://pycallgraph.slowchop.com/pycallgraph/ http://www.ohuiginn.net/mt/2009/01/pycallgraph.html
import sys
old_stdout = sys.stdout #store the real stdout
logfile = open('/some/file', 'a')
sys.stdout = logfile #redirect output to a file
#code you're debugging here
sys.stdout = old_stdout #restore the real stdout
[Obviously using logging from the start is _far_ preferable]
import sys print >>sys.stderr, "STDERR is fun."
There's not too much that suggests using this instead of logging.
import sys
def debug(*s, sep=" ", nl="\n"):
print >>sys.stderr, sep.join(map(str, s)), nl,
pass
debug("There was an error on line", 10, ":", nl="")
debug(1,2,3,4,5, sep="-")
And then comment out the line with "print" to disable it.Of course, by that point you may as well use the logging module.