这真的很棘手。让我试着给出一个更完整的答案,重用this code,以及Senthil的答案中关于getargspec
的提示,这些都在某种程度上激发了我。顺便说一句,在Python 3.0中,getargspec
已被弃用,应该使用getfullarcspec
代替。
这对我来说在Python 3.1.2上都可以工作,无论是显式调用debug函数还是使用装饰器:
def getfunc(func=None, uplevel=0):
"""Return tuple of information about a function
Go's up in the call stack to uplevel+1 and returns information
about the function found.
The tuple contains
name of function, function object, it's frame object,
filename and line number"""
from inspect import currentframe, getouterframes, getframeinfo
caller = getouterframes(currentframe())[1+uplevel]
func_name = caller[3]
frame = caller[0]
from pprint import pprint
if func:
func_name = func.__name__
else:
func = frame.f_locals.get(func_name, frame.f_globals.get(func_name))
return (func_name, func, frame, caller[1], caller[2])
def debug_prt_func_args(f=None):
"""Print function name and argument with their values"""
from inspect import getargvalues, getfullargspec
(func_name, func, frame, file, line) = getfunc(func=f, uplevel=1)
argspec = getfullargspec(func)
argvals = getargvalues(frame)
print("debug info at " + file + ': ' + str(line))
print(func_name + ':' + str(argvals))
return func_name
def df_dbg_prt_func_args(f):
"""Decorator: dpg_prt_func_args - Prints function name and arguments
"""
def wrapped(*args, **kwargs):
debug_prt_func_args(f)
return f(*args, **kwargs)
return wrapped
使用方法:
@df_dbg_prt_func_args
def leaf_decor(*args, **kwargs):
"""Leaf level, simple function"""
print("in leaf")
def leaf_explicit(*args, **kwargs):
"""Leaf level, simple function"""
debug_prt_func_args()
print("in leaf")
def complex():
"""A complex function"""
print("start complex")
leaf_decor(3,4)
print("middle complex")
leaf_explicit(12,45)
print("end complex")
complex()
并打印:
start complex
debug info at debug.py: 54
leaf_decor:ArgInfo(args=[], varargs='args', keywords='kwargs', locals={'args': (3, 4), 'f': <function leaf_decor at 0x2aaaac048d98>, 'kwargs': {}})
in leaf
middle complex
debug info at debug.py: 67
leaf_explicit:ArgInfo(args=[], varargs='args', keywords='kwargs', locals={'args': (12, 45), 'kwargs': {}})
in leaf
end complex
装饰器有点作弊:因为在wrapped
中我们得到与函数本身相同的参数,所以在getfunc
和debug_prt_func_args
中找到并报告wrapped
的ArgSpec并不重要。这段代码可能需要美化一下,但是对于我使用的简单调试测试用例来说,它已经可以正常工作了。
你可以做另一个小技巧:如果你取消注释getfunc
中的for
循环,你会发现inspect
可以给你"上下文",实际上是函数被调用的源代码行。这段代码显然没有显示任何传递给你的函数的变量内容,但有时知道在你调用的函数上面一级使用的变量名称已经足够帮助你了。
如你所见,使用装饰器,你不必改变函数内部的代码。
可能你想要漂亮地打印参数。我在函数中留下了原始打印(还有一条被注释掉的打印语句),这样更容易玩耍。
debug(**locals())
。 - Karl Knechtel