简体   繁体   English

在exec中的字符串的python回溯?

[英]python traceback of a string in exec?

I have a function which is stored in a string, which looks something like this: 我有一个存储在字符串中的函数,看起来像这样:

func_str = "def <func_name> ..."

I am evaluating it using "exec" and using it on an input as follows: 我正在使用“exec”对其进行评估,并在输入上使用它,如下所示:

exec func_str in locals()
locals()[func_name](inp)

Now this function might have an exception, and I would like to know which line caused it in the string. 现在这个函数可能有一个异常,我想知道哪一行在字符串中引起了它。 Running it in the interpreter gives me an error message which is exactly what I want: 在解释器中运行它给我一个错误消息,这正是我想要的:

  File "<string>", line 6, in <func_name>
TypeError: can only concatenate tuple (not "int") to tuple

This tells me the 6th line in my string is causing the problem. 这告诉我我的字符串中的第6行导致了问题。

Is there some way of capturing this programmatically? 有没有办法以编程方式捕获这个? I've looked at similar solutions but they don't address the exception coming from a string which was executed in the local scope. 我已经查看了类似的解决方案,但它们没有解决来自在本地范围内执行的字符串的异常。 When attempting to use the traceback module I only got the line-number for the outer function that invoked the exec. 在尝试使用回溯模块时,我只获得了调用exec的外部函数的行号。

thanks 谢谢

Well, this feels filthy and disgusting, but here You go. 嗯,这感到肮脏和恶心,但在这里你去。

sys.exc_info()[2].tb_next.tb_lineno + frameinfo.lineno

Lineno MUST be directly line above Your stringized code to eval, or if code starts at the begining of script - obviously it is not necessary. Lineno必须直接在你的字符串化代码之上排到eval,或者如果代码从脚本开头开始 - 显然没有必要。

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

output 产量

Fails at: 12
Inside: 7

if You wanted "lineno" for this stringized source only, then 如果您只想为此字符串化源提供“lineno”,那么

len(func_str.split("\n") - frameinfo.lineno

I don't know have You decided on this architecture on Your own or were forced to it, but I feel sorry :) 我不知道你有没有决定自己的这个架构或被迫它,但我感到很抱歉:)

Edit: 编辑:

If You receive string remotely 如果您远程接收字符串

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

out: 出:

Fails at: 27
Inside: 11

but this appears to be failing on excess of new lines at the end (so You'd need to strip() func_str at least) 但这似乎在最后没有超过新行(所以你至少需要strip()func_str)

I think you'll want to use eval in this case. 我想在这种情况下你会想要使用eval exec doesn't return anything: 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

Thanks to the answers, they were very helpful. 感谢答案,他们非常有帮助。

I think what I was missing was essentially a method to "go inside" the traceback stacks, as I was stopping on the outer exceptions instead of going to the absolute "root" of the failure 我认为我所遗漏的本质上是一种“进入”回溯堆栈的方法,因为我停止了外部异常,而不是去了失败的绝对“根”

this did the trick for me: 这对我有用:

def go_deeper(deeep):
  if deeep.tb_next == None:
    return deeep.tb_lineno
  else:
    return go_deeper(deeep.tb_next)

This will go to the most deep layer for the cause of the exception which is essentially all I needed. 这将是最深层的异常原因,这基本上就是我所需要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM