如何从Python中的exec或execfile获取错误的行号

jez*_*jez 10 python python-2.7

假设我有以下多行字符串:

cmd = """
    a = 1 + 1
    b = [
       2 + 2,
       4 + 4,
    ]
    bork bork bork
"""
Run Code Online (Sandbox Code Playgroud)

我想在特定范围内执行它:

scope = {}
exec( cmd, scope )
print scope[ 'b' ]
Run Code Online (Sandbox Code Playgroud)

有一个SyntaxError在命令的第6行,我希望能够向大家报告,给用户.我如何获得行号?我试过这个:

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 )
Run Code Online (Sandbox Code Playgroud)

...但是我得到了exec语句的行号,而不是多行命令中的行号.

更新:事实证明,我为此示例任意选择的异常类型SyntaxError的处理,与任何其他类型的处理不同.为了澄清,我正在寻找一种能够应对任何异常的解决方案.

use*_*342 11

对于语法错误,源行号可用作lineno异常对象本身的标志,在您的情况下存储在err.这特定于语法错误,其中行号是错误的组成部分:

>>> cmd = """
... 1 \ +
... 2 * "
... """
>>> try:
...   exec cmd
... except SyntaxError as err:
...   print err.lineno
... 
2
Run Code Online (Sandbox Code Playgroud)

如果还要处理其他错误,请添加新exceptexcept Exception, err,然后使用该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))
Run Code Online (Sandbox Code Playgroud)

例子:

>>> 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
Run Code Online (Sandbox Code Playgroud)

  • @jez通常,编辑仅用于修复,而不用于答案中的较大干预。我至少要使代码遵守PEP8。“ SyntaxError”与众不同的可能原因是它来自于编译器,而代码没有机会运行。其他错误来自运行时引擎,必须从追溯中提取行号。您可以将其视为静态语言中的编译时错误与运行时错误之间的区别-它们之所以不同,是因为它们是通过非常不同的机制在不同的时间引发的。 (2认同)