如何从 Python 中的 exec 或 execfile 获取错误的行号 [英] how to get the line number of an error from exec or execfile in Python
问题描述
假设我有以下多行字符串:
cmd = """一 = 1 + 1乙 = [2 + 2,4 + 4,]博克博克博克"""
并且我想在特定范围内执行它:
scope = {}exec( cmd, 作用域)打印范围['b']
在命令的第 6 行有一个 SyntaxError
,我希望能够将其报告给用户.我如何获得行号?我试过这个:
尝试:exec( cmd, scope ) # <-- 假设这是在源文件的第 123 行除了异常,错误:a, b, c = sys.exc_info()line_number = c.tb_lineno # <-- 这让我得到 123,而不是 6打印%s 在第 %d (%s) 行" % ( a, line_number, b.message )
...但我得到的是 exec
语句的行号,而不是多行命令中的行号.
更新:事实证明,我在本示例中任意选择的异常类型 SyntaxError
的处理与任何其他类型的处理不同.澄清一下,我正在寻找一种可以应对任何类型异常的解决方案.
对于语法错误,源行号可用作异常对象本身的 lineno
标志,在您的情况下存储在 <代码>错误代码>.这是特定于行号是错误的组成部分的语法错误:
如果还想处理其他错误,添加一个新的except
块except Exception, err
,并使用traceback
模块进行计算运行时错误的行号.
导入系统导入回溯类解释器错误(异常):通过def my_exec(cmd, globals=None, locals=None, description='source string'):尝试:exec(cmd,全局变量,本地变量)除了 SyntaxError 作为错误:error_class = err.__class__.__name__详细信息 = err.args[0]line_number = err.lineno除了作为错误的异常:error_class = err.__class__.__name__详细信息 = err.args[0]cl, exc, tb = sys.exc_info()line_number = traceback.extract_tb(tb)[-1][1]别的:返回raise InterpreterError("%s at line %d of %s: %s" % (error_class, line_number, description, detail))
示例:
<预><代码>>>>my_exec("1+1") # 也不例外>>>>>>my_exec("1+1\nbork")...InterpreterError: NameError at line 2 of source string: name 'bork' is not defined>>>>>>my_exec("1+1\nbork bork")...InterpreterError: SyntaxError at line 2 of source string: invalid syntax>>>>>>my_exec("1+1\n'''")...解释器错误:源字符串第 2 行处的语法错误:扫描三重引号字符串时的 EOFLet'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. 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.
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. 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
. 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.
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
这篇关于如何从 Python 中的 exec 或 execfile 获取错误的行号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!