我有一个存储在字符串中的函数,看起来像这样:
func_str = "def <func_name> ..."
我正在使用“exec”对其进行评估,并将其用于如下输入:
exec func_str in locals()
locals()[func_name](inp)
现在这个函数可能会出现异常,我想知道字符串中是哪一行导致的。在解释器中运行它会给我一条错误消息,这正是我想要的:
File "<string>", line 6, in <func_name>
TypeError: can only concatenate tuple (not "int") to tuple
这告诉我字符串中的第 6 行导致了问题。
是否有某种方式以编程方式捕获此信息?我看过类似的解决方案,但它们没有解决来自在本地范围内执行的字符串的异常。当尝试使用回溯模块时,我只得到了调用 exec 的外部函数的行号。
谢谢
好吧,这感觉又脏又恶心,但是给你。
sys.exc_info()[2].tb_next.tb_lineno + frameinfo.lineno
Lineno 必须直接位于要评估的字符串化代码上方,或者如果代码在脚本开头开始 - 显然没有必要。
import sys
from inspect import currentframe, getframeinfo
frameinfo = getframeinfo(currentframe())
func_str = """
def func_name(param):
d = []
u = 1
pass
a = ''
pass
print a + param
print "hi"
print "ho"
"""
exec func_str in locals()
inp = 1
try:
locals()["func_name"](inp)
except Exception as e:
print "Fails at:", sys.exc_info()[2].tb_next.tb_lineno + frameinfo.lineno
print "Inside:", len(func_str.split("\n")) - frameinfo.lineno
输出
Fails at: 12
Inside: 7
如果你只想为这个字符串化源使用“lineno”,那么
len(func_str.split("\n") - frameinfo.lineno
我不知道这个架构是你自己决定的还是被迫的,但我感到很抱歉:)
编辑:
如果您远程接收字符串
import sys
from inspect import currentframe, getframeinfo
some_item = "frameinfo = getframeinfo(currentframe())"
pass
random_items_here = 1
func_str = """
line_no = 2
lineno = 3
a_number = 0
def func_name(param):
d = []
u = 1
pass
a = ''
pass
print a + param
print "hi"
print "ho"
"""
exec some_item + "\n" + func_str in locals()
inp = 1
try:
locals()["func_name"](inp)
except Exception as e:
print "Fails at:", sys.exc_info()[2].tb_lineno
print "Inside:", len(func_str.split("\n")) - 2 - frameinfo.lineno
出:
Fails at: 27
Inside: 11
但这似乎在最后的新行过多时失败了(所以你至少需要 strip() func_str)
我想你会想在这种情况下使用
eval
。 exec
不返回任何东西:
>>> import traceback
>>> try: eval("1/0")
... except: print "Got exception:", traceback.format_exc()
...
Got exception: Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
感谢答案,他们非常有帮助。
我认为我缺少的本质上是一种“进入”回溯堆栈的方法,因为我停止在外部异常上而不是去到失败的绝对“根源”
这对我有用:
def go_deeper(deeep):
if deeep.tb_next == None:
return deeep.tb_lineno
else:
return go_deeper(deeep.tb_next)
这将进入异常原因的最深层,这基本上是我所需要的。
• Tsql 以逗号分隔列表作为参数在存储过程中执行存储过程
• 为什么 msbuild 在它从 Exec 检测到的错误行路径中引入冒号周围的空格?
• Command 'apache2ctl -S' 不使用 exec() 方法
• Splitting Unix command for use with exec [重复]
• Spring boot with Spring web更新spring boot版本后无法加载JSP
• php 中的 exec 函数在终端中工作但在 crontab 中不工作
• Maven exec-maven-plugin和maven-resources-plugin没有运行,不知道为什么。
• kubectl exec with curl Connection refused
• How to pass `ApplyConfig` to `tf.Apply()` in `hashicorp / terraform-exec`?
• lxc/lxd 启动/删除命令的 node.js child_process exec 问题
• 从“Query.prototype.exec()”检索数据的替代方案?