RE: ???: telling tracebacks to stop

Jaap Vermeulen (jaap@sequent.com)
Wed, 23 Mar 94 09:29:00 PST

| I have an application that spawns off other processes and
| executes the input (python code) it receives from them. When an
| error/exception occurs in this input I want the tracebacks to be
| printed, but I want the printing to stop before it gets to the two
| topmost frames. The last two frames printed are ALWAYS THE SAME
| becuase they are the ineer loops in which I'm reading and executing
| this input. This is an implementation detail that I would rather my
| users not have to deal with when trying to debug their code.

You will have to print your own stacktrace. You can just skip the first two
frames (or however many you want to skip).

try:
exec(...)
except (KeyboardInterrupt, SystemExit):
sys.exit() # You probably don't need a stacktrace here
except:
stacktrace(sys.exc_value, sys.exc_type,
sys.exc_traceback.tb_next.tb_next) # Skip two frames

You can just pick apart the stackframe and print the interesting
information. You can even reverse the printing order of the stackframes (I
find it more intuitive to print the innermost stackframe first). I included
a version of stacktrace that I sometimes use.

| I know that by setting sys.tracebacklimit I can keep the
| number of tracebacks printed to a constant limit, but what I want is
| to just make sure a traceback print rolls through all but the LAST TWO
| levels? This means that the number of tracebacks printed will vary

Seems like a perfect extension to sys.tracebacklimit. If you make it
negative, it will print (total - abs(sys.tracebacklimit)) stackframes.

-Jaap-

------- Sample implementation of stacktrace

#
# Prints innermost first, and only line number. If consecutive frames are
# from the same file, it print the linenumbers on the same line after the
# file or module name. It doesn't print the offending line.
#

import sys, os

def stacktrace(type, value, traceback):
if value:
print type + ': ' + str(value)
else:
print type
print 'Stacktrace (innermost first):'
discard = pick_apart(traceback)
print
sys.exit(2)

def pick_apart(tb)

if tb: last_file = pick_apart(tb.tb_next)
else: return

file = tb.tb_frame.f_code.co_filename
line = tb.tb_frame.f_lineno

if file != last_file:
if file[-3:] == '.py':
module = os.path.split(file)[1][:-3]
sys.stdout.write('\n Module ' + `module`)
else:
sys.stdout.write('\n File ' + `file`)
sys.stdout.write(': line ' + `line`)
else:
sys.stdout.write(', line ' + `line`)
return file