Still Pretty Cheap Debugging Trick
After reading Uche Ogbuji's
cheap debugging trick, I looked a bit more at inspect.stack(). It wasn't very hard
to make a sort of ad hoc traceback, but without actually causing an
exception. My particular motivation was a case where some code was being
cause twice where it should only be called once. I sometimes just put
assert 0 in someplace to find when it is called, but then it
would catch the first correct usage and never get to the second. So I
put a function call in the overly-called code, logPoint(), and
I got a list of tracebacks. The code:
import inspect
from cStringIO import StringIO
def logPoint(msg=''):
stack = inspect.stack()
# get rid of logPoint's part of the stack:
stack = stack[1:]
stack.reverse()
output = StringIO()
if msg:
output.write(str(msg) + '\n')
for stackLine in stack:
frame, filename, line, funcname, lines, unknown = stackLine
if filename.endswith('/unittest.py'):
# unittest.py code is a boring part of the traceback
continue
if filename.startswith('./'):
filename = filename[2:]
output.write('%s:%s in %s:\n' % (filename, line, funcname))
output.write(' %s\n' % ''.join(lines)[:-1])
s = output.getvalue()
# I actually logged the result, but you could also print it:
print s
Update: Maybe print_stack() in the
traceback
is an easier way to do this? The only real advantage to this way is that
you can hide parts of the stack that are boring -- usually the
framework, be it unittest, a web framework, the interactive interface,
etc.
Created 05 Aug '04
Modified 14 Dec '04
It looks like there's an extra parenthesis on the line, "if
(filename.endswith".
Indeed; fixed.
I wonder whether your code would be acceptable as a replacement for
traceback.print_stack() - for people who don't want it to use the
exception hack. Not that I've ever had a problem with that.
iRichard, If that's a really problem, why not just change
traceback.print_stack() to use sys._getframe()?
(traceback.print_stack() and traceback.print_stack(sys._getframe())
gives the same output)
See also
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52215
which shows how to dump the local variables from each frame as well.
That makes the debugging really easy.
Wouldn't trace.py (the sys.settrace wrapper) be as clean a way to
have solved the original problem?