0

When error occured Python prints something like this:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 8, in m
  File "<stdin>", line 5, in exec_st
  File "<stdin>", line 9, in exec_assign
  File "<stdin>", line 48, in ref_by_id
IndexError: list index out of range

where 2, ... , 48 are relative line numbers which are not very convenient. How to print absolute line numbers in such error messages?

EDIT: Maybe it's a dumb question, but answer will facilitate development a little. I'm printing text in several files. When done, press shortcut which runs python and copies contents of current file to console. Proposed solution forces to press excess keystrokes (Ctrl+S, Alt+Tab) and create additional files. I hope I have put it clear.

DSblizzard
  • 4,007
  • 7
  • 48
  • 76
  • 4
    Run your program from a file rather than entering at the console or piping it in? – Managu Jun 08 '12 at 02:56
  • Thank you, but I want programmatic solution also. – DSblizzard Jun 08 '12 at 03:05
  • 2
    Maybe you could expand your question some? It's not clear to me what you mean by absolute/relative line number. And I'm simply baffled by all the `""`s up there. What are you trying to do, and why? In particular, what is the objection to running your program from a disk file (which I think would solve your problem)? – Managu Jun 08 '12 at 03:12
  • This looks somewhat relevant: http://stackoverflow.com/questions/1278705/python-when-i-catch-an-exception-how-do-i-get-the-type-file-and-line-number – Alex W Jun 08 '12 at 03:14
  • Maybe you could present to us a (very simplified) version of your input, the actual output you're getting, and what you'd like to get? – Managu Jun 08 '12 at 03:18

2 Answers2

2

A few minutes of hacking around gives me this Read-Eval-Print Loop in Python 2.7:

#!/usr/bin/env python
import code
import sys

LINE_NUMBER=0

def reset_linenum():
    global LINE_NUMBER
    LINE_NUMBER=-1

def resettable_REPL():
    global LINE_NUMBER
    BUFFERED_LINES=[]
    ii=code.InteractiveInterpreter({"reset_linenum":reset_linenum})
    while True:
        try:
            BUFFERED_LINES.append(raw_input("!"+sys.ps1)+'\n')
            while (BUFFERED_LINES[-1][:1] in " \t" or
                   ii.runsource("\n"*LINE_NUMBER+"".join(BUFFERED_LINES), "console")):
                BUFFERED_LINES.append(raw_input("!"+sys.ps2)+'\n')
            LINE_NUMBER+=len(BUFFERED_LINES)
            BUFFERED_LINES=[]
        except EOFError:
            break

if __name__=='__main__':
    resettable_REPL()

It's a bit hackish, but it keeps track of line numbers as the session continues, and allows the current count to be reset by a call to reset_linenum(). An example session:

!!!> print "hello"              # line 1
hello
!!!> def badfunc():             # line 2
!...     raise Exception("doh") # line 3
!!!> badfunc()                  # line 4
Traceback (most recent call last):
  File "console", line 4, in <module>
  File "console", line 3, in badfunc
Exception: doh
!!!> ?                          # line 5
  File "console", line 5
    ?
    ^
SyntaxError: invalid syntax
!!!> reset_linenum()            # RESET
!!!> raise Exception("!")       # line 1
Traceback (most recent call last):
  File "console", line 1, in <module>
Exception: !
!!!> 

EDIT: Fixed REPL to not execute indented blocks quite so prematurely.

Managu
  • 8,849
  • 2
  • 30
  • 36
  • Super! Though it's a bit buggy and overkill, I think. ` !!!> # unique string id !!!> def usid(): !... global Uid !!!> Uid += 1 File "", line None SyntaxError: unexpected indent (console, line 4) !!!> return str(Uid) # File "", line None SyntaxError: unexpected indent (console, line 5)` – DSblizzard Jun 08 '12 at 04:44
  • Yup, caught that problem after initial post. Try now? – Managu Jun 08 '12 at 04:51
  • It works. If nobody will post more "lightweight" answer I'll accept this. – DSblizzard Jun 08 '12 at 05:04
1

Doing this on Linux? Instead of having your hotkey invoke python directly, have it invoke this shell script:

#!/bin/bash
cat > /tmp/$$.py
/usr/bin/env python /tmp/$$.py
rm -f $$.py

You might also try (might even work on Windows):

import sys
exec(compile("".join([line for line in sys.stdin]), "console", "single"))
Managu
  • 8,849
  • 2
  • 30
  • 36
  • How to exit from input to "compile"? Ctrl+D prints "^D", Ctrl+C prints "Traceback (most recent call last): File "", line 1, in KeyboardInterrupt" – DSblizzard Jun 08 '12 at 05:13
  • It's Ctrl+Z hotkey. But second snippet doesn't work properly, unfortunately. – DSblizzard Jun 08 '12 at 05:23
  • *shrug* Overkill? Underkill? A much simpler approach, with correspondingly less functionality – Managu Jun 08 '12 at 05:26