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
user4815162342
source share