can error messages be improved or can they be overridden ?

rdmurray at bitdance.com rdmurray at bitdance.com
Mon Feb 23 20:40:59 EST 2009


"andrew cooke" <andrew at acooke.org> wrote:
> rdmurray at bitdance.com wrote:
> [...]
> > (You know, I really ought to revisit that routine and make it part
> > of my standard development toolbox.)
> 
> please post it....

OK.  I dug it up, cut out the stuff that was specific to the application,
freshened it up a little, and added a little demo.  I don't claim this
is the best possible way to do this (it certainly could be made smarter,
possibly by using python facilities to actually parse the line; right
now it takes a very brute force approach to trying to find variables),
but it served my purposes and perhaps it will help others.

Oh, yeah, and I just added the globals bit without thoroughly testing
it...I think it probably doesn't help much and may be misleading when
the traceback is thrown in an imported module.

Enjoy.

--RDM

------------------------------------------------------------------
from traceback import format_tb, format_exception_only
from sys import exc_info
from re import compile
varsplitter = compile("[^0-9a-zA-Z_]")

def format_exception():
    """
    Add a dump of any variables we can identify from the failing program
    line to the end of the traceback.  The deep mojo for doing this came
    from an example in the Zope core plus documentation in the Python
    Quick Reference.
    """
    etype, value, tb = exc_info()
    plaintb = format_tb(tb)
    result=['Traceback (innermost last):']
    for line in plaintb:
        result.append(line)
        f = tb.tb_frame
        tb = tb.tb_next
    locals=f.f_locals
    vars = varsplitter.split(line.split('\n')[-2])
    dvars = set()
    self = None
    if 'self' in locals: self = locals['self']
    for v in vars:
        if v in dvars: continue
        dvars.add(v)
        if v in locals:
            result.append('      %s: %r\n' % (v,locals[v]))
        if self and hasattr(self, v):
            result.append('      self.%s: %r\n' % (v,getattr(self, v)))
        if v in globals():
            result.append('      (global) %s: %r\n' % (v,globals()[v]))
    result.extend(format_exception_only(etype, value))
    return ''.join(result)


class Demo:
    y = 200
    def __init__(self, x):
        self.x = x

    def bad(self):
        x = [1, 2]
        y = (5, 9, 9)
        y[1] = x[2] + foo

foo = 'a value'

def main():
    bar = Demo('some value')
    bar.bad()

  
if __name__=='__main__':
    try: main()
    except Exception:
        print format_exception()

------------------------------------------------------------------
rdmurray at maestro:~>python tb.py
Traceback (innermost last):  File "tb.py", line 56, in <module>
    try: main()
  File "tb.py", line 52, in main
    bar.bad()
  File "tb.py", line 46, in bad
    y[1] = x[2] + foo
      y: (5, 9, 9)
      self.y: 200
      x: [1, 2]
      self.x: 'some value'
      (global) foo: 'a value'
IndexError: list index out of range
------------------------------------------------------------------




More information about the Python-list mailing list