Web apps, tracebacks and emacs -- a rough recipe

Erwin S. Andreasen erwin at andreasen.com
Thu Aug 22 21:58:49 CEST 2002

The last couple of days, I've been spending a lot of time working on a
web application. Often I get a traceback in my browser, switch to
emacs, switch to the file that caused it, go to the line with the
problem and perhaps check back to see what the values of locals in the
frame were.

I decided to try to to automate this process.

First, I changed my application to emit tracebacks with the mime
content type "text/x-python-traceback".

Then I set up my browser, Opera, to run a program whenever it got such
a file. This should be easily possible in Mozilla as well.

The program analyzes the traceback file and invokes (using gnuclient
-batch) a function in my xemacs, giving it 3 arguments: the traceback
file, the source file that has the top level frame and the line in
that file (originally the Python script did more work, what's left is
simple enough so it could be integrated into the elisp code).

The elisp function then simply inserts the traceback file on top of a
*traceback* buffer and loads up the file with error. Here's the elisp
code (note that I always have my frame split into two windows
horizontally, where the left is slightly larger and the primary window
-- thus all the use of *-other-window)

(defun display-python-traceback (traceback-file source-file source-line)
  (switch-to-buffer-other-window (get-buffer-create "*traceback*"))
  (insert-file traceback-file)

  (search-forward "\n\n")
  (forward-line -2)
   (make-extent (point) (progn (forward-line 1) (point))) 'face '(red))

  (find-file-other-window source-file)
  (goto-line source-line)

You can skip the middle part if you aren't using xemacs: I use it to
highlight the line with the error message in it. I'll have to mention
that the tracebacks I use look like this:

Error text: Variable value not found (hermes.Style.StyleUsageError)
Traceback (most recent call last):
  File "./iris/Dispatcher.py", line 30, in dispatch
    res = fun(r, rest)
  [... more stack frames ... ]
  File "./hermes/Style.py", line 168, in replacer
    raise StyleUsageError('Variable %s not found' % x.group(1))
StyleUsageError: Variable value not found

** Locals:
_args                 {'name': 'oe23.0', 'value': None, 'size': 20}
[... more locals follow ...]

The python script itself is also fairly simple. To make it easier to
parse the traceback, I modified the code that formats traceback to
emit this line:

*file: /full/path/name lineno

since only the relative path is displayed in modules imported with
relative names.

import sys, util, re, os
FileRx = re.compile(r'\*file: (.+) (\d+)')

m = FileRx.search(open(sys.argv[1]).read())
assert m

file, line = m.group(1,2)
os.popen('gnuclient -batch', 'w').write(
    '(display-python-traceback "%s" "%s" %s)' % (sys.argv[1], file, line))

os.system('sawfish-client -e "(select-workspace 1)"')

As my emacs is on a different workspace than my web browser, I also
tell sawfish to switch workspace to there.

That's it -- one nice expansion would be to make emacs parse the
traceback file entirely and allow you to switch between stack frames
using some hotkey (perhaps even highlighting the current frame in the
*traceback* buffer).

<erwin at andreasen.org>                           Herlev, Denmark     
<URL:http://www.andreasen.org/>                             <*>   

More information about the Python-list mailing list