【问题标题】:how to get the line number of an error from exec or execfile in Python如何从 Python 中的 exec 或 execfile 获取错误的行号
【发布时间】:2015-05-04 08:33:26
【问题描述】:

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

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

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

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

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

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 )

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

更新:事实证明,我为这个示例任意选择的异常类型 SyntaxError 的处理不同于任何其他类型的处理。澄清一下,我正在寻找一种可以应对任何异常的解决方案。

【问题讨论】:

  • 你看过pdb吗?

标签: python python-2.7


【解决方案1】:

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

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

如果您还想处理其他错误,请添加新的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))

例子:

>>> 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

【讨论】:

  • 有趣!我没想到SyntaxError 与其他类型不同。当然,我也希望能够报告其他错误。你的回答让我走上了正轨。这样我就可以将其标记为已接受,如果您不介意,我将编辑您的答案以包含这导致我得到的完整解决方案(因此,如果您认为应该如此,您可以进一步改进它)。
  • @jez 通常,编辑保留用于修复,而不是用于对答案进行大规模干预。我至少会让代码遵守 PEP 8。SyntaxError 不同的可能原因是它在代码有机会运行之前来自编译器。其他错误来自运行时引擎,必须从回溯中提取行号。你可以把它想象成静态语言中编译时错误和运行时错误之间的区别——它们是不同的,因为它们是由非常不同的机制在不同的时间引发的。
  • 注意所有方面。通常我会在 pep8 面前大笑,但我认为,你的空间是你的规则。当然,如果您认为不合适,请删除它-我只是想接受您的答案,因为它使我找到了解决方案,并希望接受的答案包含完整的解决方案(使用您建议的方法来编写我自己的答案是错误的然后我接受)
  • @jez 谢谢。出于好奇,为什么要“面对pep8笑”?我倾向于遵守“当在罗马时……”——例如,在编写 Java 时,我使用 camelCaseMyMethods 等等。
  • 每次我选择说拉丁语时,我都不认为自己是在罗马。 pep8 上有很多常识性的东西,但也有很多高度主观的东西,其中一个人的“可读性更强”是另一个人的“可读性差”,甚至有一两个问题我发现自己处于“圣战”(例如制表符与空格)。我的代码需要由我而不是 Guido 最大程度地可读/可维护——至于第三方,我认为他们可能更喜欢一组任意的约定。
猜你喜欢
  • 2018-11-14
  • 2016-08-24
  • 1970-01-01
  • 2017-10-04
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2019-06-01
相关资源
最近更新 更多