全部,
我有一个类似于问题 2617120 的问题,可在此处找到:
提问者希望通过跟踪钩子(Hook)执行时如何制作 python 打印输出函数参数的指针。
我正在寻找与此非常相似但有所不同的东西。我不想转储所有数据,而是希望在代码运行时对其进行评估,并打印出所有评估的变量。例如,使用以下代码:
for modname in modnames:
if not modname or '.' in modname:
continue
...
跟踪 Hook 会导致打印出以下内容:
for modname in modnames: | for init in init,., encoding
|
if not modname or '.' in modname: | if not init or '.' in init
continue | continue
if not modname or '.' in modname: | if not . or '.' in .
... |
代码行根据运行帧进行插值。我在 perl 中完成了此操作,在某些情况下它是救命稻草。
有人知道在 python 中执行此操作的最佳方法吗?我有我的想法,但我想听听人们的想法(以及他们是否有任何预先制定的解决方案)
这里顺便说一下引用代码:
import sys
import linecache
import random
def traceit(frame, event, arg):
if event == "line":
lineno = frame.f_lineno
filename = frame.f_globals["__file__"]
if filename == "<stdin>":
filename = "traceit.py"
if (filename.endswith(".pyc") or
filename.endswith(".pyo")):
filename = filename[:-1]
name = frame.f_globals["__name__"]
line = linecache.getline(filename, lineno)
print "%s:%s:%s: %s" % (name, lineno,frame.f_code.co_name,line.rstrip())
return traceit
def main():
print "In main"
for i in range(5):
print i, random.randrange(0, 10)
print "Done."
sys.settrace(traceit)
main()
最佳答案
给定 line
中的一行文本,这里有一个快速技巧可能会给您一些帮助。和 frame
中的当前堆栈帧(顺便说一下,这是 traceit
的内部函数)。
import re
from types import *
def interpolatevar(matchobj):
excludetypes = set((NoneType, TypeType, FunctionType, LambdaType, ClassType,
CodeType, InstanceType, MethodType, BuiltinFunctionType,
BuiltinMethodType))
var = matchobj.group(0)
basevar = var.split(".")[0]
if basevar in frame.f_code.co_names or basevar in frame.f_code.co_varnames:
if basevar in frame.f_globals or basevar in frame.f_locals:
val = eval(var, frame.f_globals, frame.f_locals)
if type(val) not in excludetypes:
return repr(val)
return var
line = re.sub(r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*",
interpolatevar, line)
由于它使用正则表达式来查找标识符,即使它们在字符串文字中,它也会愚蠢地找到它们,但标识符必须在函数中实际使用并在本地或全局范围内定义。
它确实处理对象属性访问(例如 foo.bar
将被该值替换),我最初发布的版本不会,并且它会过滤掉自替换 foo
以来的各种类型的值。与 <function foo at 0x02793470>
并没有真正告诉你很多你还不知道的事情。 (排除列表很容易定制,当然,如果您对这些类型的某些值感兴趣,或者您可以从 types
模块添加其他值。)
从长远来看,我认为查看该行的字节码可能会有利可图,因为这样更容易识别哪些标记实际上是标识符。 ast
模块也可用于生成语句的解析树,它可以让您弄清楚标识符是什么,但是当您一次只看到一行时,这对于条件和循环来说是有问题的。
关于python - 改进 python 中的堆栈跟踪钩子(Hook),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4383895/