Traceback and source code

Jarno J Virtanen jajvirta at cc.helsinki.fi
Wed Dec 13 16:43:09 CET 2000


I'd be interested to know how the traceback module is syncronized
with the actual source code (file). The trouble I keep having is
that traceback reports the corresponding line number correctly,
but the actual source code line is not always correct. I'm not
saying here that traceback module is incorrect or anything, I'd
just be happy to know if I'm doing something wrong or what could
be done to fix the problem. [I'm using python 1.5.2 on a Linux box,
if that's of any significance.]

The problem appears like this:

File "spam.py", line 22, in do_spam
    def do_eggs(self, args):
NameError: BUG

The longer explanation how I got there follows (it's a bit long though):

Suppose a programmer named Terry is assigned to design and implement
a command line interface called Spam. It is to be designed so that the
Spam source code can be reloaded while the program is running and that
it catches errors, prints them and lets the user continue running the
program. Well, Terry decides to split the code to a module that catches
the errors and reloads the other module and to a module that has the
actual features. The Error Catcher code he places in a file named 
main.py that has following source code:

import os, sys, string, traceback

while 1:
    try:
        import spam
        rspam = spam.Spam()
        rspam.cmdloop()
    except spam.reload:
        try:
            reload(spam)
        except:
	    sys.exc_traceback = sys.last_traceback = None
            traceback.print_exc(file=sys.stdout)
    except spam.exit:
        break
    except:
        sys.exc_traceback = sys.last_traceback = None
        traceback.print_exc(file=sys.stdout)

(that sys.exc_traceback = etc. expression I fished from the python
FAQ but it doesn't seem to help and didn't it seem to be the
issue, but one never knows :-)

The actual command line interface goes to file named spam.py:

import readline, cmd, sys

exit = 'exit spam'
reload = 'reload spam'

class Spam(cmd.Cmd):

    prompt = '>>> '

    def do_quit(self, args):
        raise exit

    def do_reload(self, args):
        raise reload

    def do_spam(self, args):
        print 'spam'
        
    def do_eggs(self, args):
        print 'eggs'


Now Terry wants to add more features in the command line interface.
He modifies the spam method to make it more useful:

    def do_spam(self, args):
        print 'spam'
        BUG

Excited as he is of the quick evolution of the Spam he issues reload
and spam commands in the CLI:

>>> reload
>>> spam
spam
Traceback (innermost last):
  File "main.py", line 7, in ?
    rspam.cmdloop()
  File "/usr/lib/python1.5/cmd.py", line 77, in cmdloop
    stop = self.onecmd(line)
  File "/usr/lib/python1.5/cmd.py", line 115, in onecmd
    return func(arg)
  File "spam.py", line 18, in do_spam
    BUG
NameError: BUG

Damn it, Terry says, I've made a BUG. Frustrated from the setback
he decides to go for a coffee to get things sorted in his head. Before
that he makes a reminder to the source code that there's a BUG 
somewhere. Furthermore he notices that the BUG is in the do_spam
-method:

    # There's a BUG here somewhere, fix it!

    def do_spam(self, args):
        print 'spam'
        BUG


As soon as he gets to the coffee machine he remebers and shouts: "Of
course, I made a BUG!". He runs back to his office and as he is 
running he rethinks the solution over and over again and begins
to think that he has already fixed it and issues reload and spam
again:

>>> reload
>>> spam
spam
Traceback (innermost last):
  File "main.py", line 7, in ?
    rspam.cmdloop()
  File "/usr/lib/python1.5/cmd.py", line 77, in cmdloop
    stop = self.onecmd(line)
  File "/usr/lib/python1.5/cmd.py", line 115, in onecmd
    return func(arg)
  File "spam.py", line 20, in do_spam
    def do_eggs(self, args):
NameError: BUG

(Terry gets even more frustrated and the rest is history ;-)




More information about the Python-list mailing list