def pm(dbg_cmds=None, frameno=1, p=None): """Set up post-mortem debugging using the last traceback. But if there is no traceback, we'll assume that sys.exc_info() contains what we want and frameno is the index location of where we want to start. 'dbg_cmds' is an optional list of debugger commands you want to run. 'p', is an optional pydb.Pdb object. """ tb = fns.get_last_tb_or_frame_tb() post_mortem(tb, dbg_cmds=dbg_cmds, p=p) return
def post_mortem(t=None, dbg_cmds=None, cmdfile=None, frameno=1, p=None): """Enter debugger read loop after your program has crashed. If no traceback parameter, t, is supplied, the last traceback and if that doesn't exist either we'll assume that sys.exec_info() contains what we want and frameno is the index location of where we want to start. 'dbg_cmds' is an optional list of debugger commands you want to run. 'cmdfile' is an optional debugger command file you want to run "source" on. 'frameno' specifies how many frames to ignore in the traceback. The default is 1 - we don't need the call to post_mortem. If you have wrapper functions that call this one, you may want to increase frameno. """ if p == None: p = Pdb() p.reset() p.running = False re_bogus_file = re.compile("^<.+>$") if t is None: # frameno+1 because we are about to add one more level of call # in get_last_tb_or_frame_tb t = fns.get_last_tb_or_frame_tb(frameno+1) if t is None: print "Can't find traceback for post_mortem " + \ "in sys.last_traceback or sys.exec_info()" return # t has least-recent traceback entry first. We want the most-recent # entry. Also we'll pick out a mainpyfile name if it hasn't previously # been set. while t.tb_next is not None: filename = t.tb_frame.f_code.co_filename if 0 == len(p.mainpyfile) and not re_bogus_file.match(filename): p.mainpyfile = filename t = t.tb_next p.curframe = t.tb_frame if dbg_cmds != None: p.cmdqueue = list(dbg_cmds) if 0 == len(p._program_sys_argv): # Fake program (run command) args since we weren't called with any p._program_sys_argv = list(sys.argv[1:]) p._program_sys_argv[:0] = [p.mainpyfile] if 0 == len(p._sys_argv): # Fake script invocation (restart) args since we don't have any p._sys_argv = list(p._program_sys_argv) p._sys_argv[:0] = [__title__] if cmdfile is not None: p.do_source(cmdfile) try: # FIXME: This can be called from except hook in which case we # need this. Dunno why though. try: _pydb_trace.set_trace(t.tb_frame) except: pass # Possibly a bug in Python 2.5. Why f.f_lineno is # not always equal to t.tb_lineno, I don't know. f = t.tb_frame if f and f.f_lineno != t.tb_lineno : f = f.f_back p.interaction(f, t) except Restart: while True: sys.argv = list(p._program_sys_argv) p.msg("Restarting %s with arguments:\n\t%s" % (p.filename(p.mainpyfile), " ".join(p._program_sys_argv[1:]))) try: p._runscript(p.mainpyfile) if p._user_requested_quit: break if p.noninteractive: break except Restart: pass except BdbQuit: pass return
def post_mortem(t=None, dbg_cmds=None, cmdfile=None, frameno=1, p=None, stdout=None): """Enter debugger read loop after your program has crashed. If no traceback parameter, t, is supplied, the last traceback and if that doesn't exist either we'll assume that sys.exc_info() contains what we want and frameno is the index location of where we want to start. 'dbg_cmds' is an optional list of debugger commands you want to run. 'cmdfile' is an optional debugger command file you want to run "source" on. 'frameno' specifies how many frames to ignore in the traceback. The default is 1 - we don't need the call to post_mortem. If you have wrapper functions that call this one, you may want to increase frameno. """ if p == None: p = Pdb(stdout=stdout) pass p.reset() p.running = False re_bogus_file = re.compile("^<.+>$") if t is None: # frameno+1 because we are about to add one more level of call # in get_last_tb_or_frame_tb t = fns.get_last_tb_or_frame_tb() if t is None: print "Can't find traceback for post_mortem " + \ "in sys.last_traceback or sys.exec_info()" sys.stdout.flush() return # t has least-recent traceback entry first. We want the most-recent # entry. Also we'll pick out a mainpyfile name if it hasn't previously # been set. while t.tb_next is not None: filename = t.tb_frame.f_code.co_filename if 0 == len(p.mainpyfile) and not re_bogus_file.match(filename): p.mainpyfile = filename t = t.tb_next p.curframe = t.tb_frame if dbg_cmds != None: p.cmdqueue = list(dbg_cmds) if 0 == len(p._program_sys_argv): # Fake program (run command) args since we weren't called with any p._program_sys_argv = list(sys.argv[1:]) p._program_sys_argv[:0] = [p.mainpyfile] if 0 == len(p._sys_argv): # Fake script invocation (restart) args since we don't have any p._sys_argv = list(p._program_sys_argv) p._sys_argv[:0] = [__title__] if cmdfile is not None: p.do_source(cmdfile) try: # FIXME: This can be called from except hook in which case we # need this. Dunno why though. try: _pydb_trace.set_trace(t.tb_frame) except: pass # Possibly a bug in Python 2.5. Why f.f_lineno is # not always equal to t.tb_lineno, I don't know. f = t.tb_frame if f and f.f_lineno != t.tb_lineno: f = f.f_back p.interaction(f, t) except Restart: while True: sys.argv = list(p._program_sys_argv) p.msg( "Restarting %s with arguments:\n\t%s" % (p.filename(p.mainpyfile), " ".join(p._program_sys_argv[1:]))) try: p._runscript(p.mainpyfile) if p._user_requested_quit: break if p.noninteractive: break except Restart: pass except BdbQuit: pass return