我如何检查sys.settrace调用中函数参数的值?似乎我有可能输出除了参数之外的所有东西(行,文件名,堆栈跟踪,返回值等)。是否有一种解决方法可以让我跟踪函数参数值?

答案 0 :(得分:11)
您可以使用代码对象和框架对象的组合。
请参阅Python Data-Model Reference中的相关说明。
import sys
def fn(frame, msg, arg):
if msg != 'call': return
# Filter as appropriate
if frame.f_code.co_filename.startswith("/usr"): return
print("Called", frame.f_code.co_name)
for i in range(frame.f_code.co_argcount):
name = frame.f_code.co_varnames[i]
print(" Argument", name, "is", frame.f_locals[name])
sys.settrace(fn)
def hai(a, b, c):
print(a, b, c)
hai("Hallo", "Welt", "!")
要意识到的关键是
f_locals
。f_code.co_varnames
。答案 1 :(得分:0)
我将Marcs答案变成了可用于检查其他脚本的脚本:
print_func_calls.py:
#!/usr/bin/env python
import sys
# opt-out file names which start with one of these prefixes
FILENAME_FILTER = {"/usr", "<"}
# opt-in file names again which match one of these prefixes
FILENAME_UNFILTER = {"/lib/python/some-important-module"}
# opt-out function names
FN_NAME_FILTER = {"<module>", "__new__", "__setattr__", "<lambda>"}
def to_str(exp):
"""Turn an argument value into a string without dying on exceptions"""
try:
return repr(exp)[:100]
except Exception as exc:
return "n/a"
def fn(frame, msg, arg):
if msg != 'call':
return
filename, fn_name = frame.f_code.co_filename, frame.f_code.co_name
if (not all(not filename.startswith(p) for p in FILENAME_FILTER) and
all(not filename.startswith(p) for p in FILENAME_UNFILTER) or
fn_name in FN_NAME_FILTER):
return
argstr = ", ".join("%s=%s" % (
frame.f_code.co_varnames[i], to_str(frame.f_locals[frame.f_code.co_varnames[i]]))
for i in range(frame.f_code.co_argcount))
print(">>> %s::\033[37m%s\033[0m(%s)" % (filename, fn_name, argstr))
sys.settrace(fn)
sys.argv = sys.argv[1:]
exec(open(sys.argv[0]).read())
像这样使用它:
print_func_calls.py my-script.py arg1..argN