How to get error line number from exec or execfile in Python

Let's say I have the following multiline line:

cmd = """ a = 1 + 1 b = [ 2 + 2, 4 + 4, ] bork bork bork """ 

and I want to execute it in a specific area:

 scope = {} exec( cmd, scope ) print scope[ 'b' ] 

There is a SyntaxError on line 6 of the command, and I want to be able to report this to the user. How to get line number? I tried this:

 try: exec( cmd, scope ) # <-- let say this is on line 123 of the source file except Exception, err: a, b, c = sys.exc_info() line_number = c.tb_lineno # <-- this gets me 123, not 6 print "%s at line %d (%s)" % ( a, line_number, b.message ) 

... but I get the line number of the exec statement, not the line number in the multi-line command.

Update: it turns out the processing of the type of exception that I arbitrarily chose for this example, SyntaxError , is different from the processing of any other type. To clarify, I'm looking for a solution that handles some kind of exception.

+7
python
source share
1 answer

For syntax errors, the source line number is available as the lineno flag for the exception object itself, in your case it is stored in err . This is specific to syntax errors when the line number is an integral part of the error:

 >>> cmd = """ ... 1 \ + ... 2 * " ... """ >>> try: ... exec cmd ... except SyntaxError as err: ... print err.lineno ... 2 

If you want to handle other errors as well, add a new block except except Exception, err and use the traceback module to calculate the line number for the runtime error.

 import sys import traceback class InterpreterError(Exception): pass def my_exec(cmd, globals=None, locals=None, description='source string'): try: exec(cmd, globals, locals) except SyntaxError as err: error_class = err.__class__.__name__ detail = err.args[0] line_number = err.lineno except Exception as err: error_class = err.__class__.__name__ detail = err.args[0] cl, exc, tb = sys.exc_info() line_number = traceback.extract_tb(tb)[-1][1] else: return raise InterpreterError("%s at line %d of %s: %s" % (error_class, line_number, description, detail)) 

Examples:

 >>> my_exec("1+1") # no exception >>> >>> my_exec("1+1\nbork") ... InterpreterError: NameError at line 2 of source string: name 'bork' is not defined >>> >>> my_exec("1+1\nbork bork bork") ... InterpreterError: SyntaxError at line 2 of source string: invalid syntax >>> >>> my_exec("1+1\n'''") ... InterpreterError: SyntaxError at line 2 of source string: EOF while scanning triple-quoted string 
+7
source share

All Articles