[英]how to get the line number of an error from exec or execfile in Python
Let's say I have the following multi-line string: 假设我有以下多行字符串:
cmd = """
a = 1 + 1
b = [
2 + 2,
4 + 4,
]
bork bork bork
"""
and I want to execute it in a particular scope: 我想在特定范围内执行它:
scope = {}
exec( cmd, scope )
print scope[ 'b' ]
There's a SyntaxError
at line 6 of the command, and I want to be able to report that to the user. 在命令的第6行有一个
SyntaxError
,我希望能够向用户报告。 How do I get the line number? 我如何获得行号? I've tried this:
我试过这个:
try:
exec( cmd, scope ) # <-- let's 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 within the multi-line command. ...但是我得到了
exec
语句的行号,而不是多行命令中的行号。
Update: it turns out the handling of the type of exception that I arbitrarily chose for this example, the SyntaxError
, is different from the handling of any other type. 更新:事实证明,我为此示例任意选择的异常类型的处理,
SyntaxError
,与处理任何其他类型不同。 To clarify, I'm looking a solution that copes with any kind of exception. 为了澄清,我正在寻找一种能够应对任何异常的解决方案。
For syntax errors, the source line number is available as the lineno
flag on the exception object itself, in your case stored in err
. 对于语法错误,源行号可用作异常对象本身的
lineno
标志,在您的情况下存储在err
。 This is specific to syntax errors where 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 also handle other errors, add a new except
block except Exception, err
, and use the traceback
module to compute the line number for the runtime error. 如果还要处理其他错误,请添加
except Exception, err
的新except
块,并使用traceback
模块计算运行时错误的行号。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.