Das ist wirklich schwierig. Lassen Sie mich versuchen und eine umfassendere Antwort geben this code, und den Hinweis über getargspec
in Senthil Antwort, die mich irgendwie ausgelöst hat. Btw, getargspec
ist in Python 3.0 und getfullarcspec
should be used veraltet.
Dies funktioniert für mich auf einem Python 3.1.2 sowohl mit explizit die Debug-Funktion aufrufen und mit einem Dekorateur mit:
# from: https://stackoverflow.com/a/4493322/923794
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
#for (level, frame) in enumerate(getouterframes(currentframe())):
# print(str(level) + ' frame: ' + str(frame))
caller = getouterframes(currentframe())[1+uplevel]
# caller is tuple of:
# frame object, filename, line number, function
# name, a list of lines of context, and index within the context
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)
#print(argspec)
argvals = getargvalues(frame)
print("debug info at " + file + ': ' + str(line))
print(func_name + ':' + str(argvals)) ## reformat to pretty print arg values here
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
Verbrauch:
@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()
und Drucke:
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
Der Dekorateur betrügt ein bisschen: Seit wrapped
bekommen wir das gleiche a rguments als Funktion selbst ist es egal, dass wir die ArgSpec von wrapped
in getfunc
und debug_prt_func_args
finden und melden. Dieser Code könnte ein wenig verschönert werden, aber es funktioniert jetzt gut für die einfachen Debug-Testfälle, die ich benutzt habe.
Ein weiterer Trick, den Sie tun können: Wenn Sie die for
-loop in getfunc
Kommentar- können Sie sehen, dass inspect
können Sie den „Kontext“ geben, die wirklich die Zeile des Quellcodes ist, wo eine Funktion aufgerufen wurde.Dieser Code zeigt offensichtlich nicht den Inhalt einer Variablen an, die Ihrer Funktion zugewiesen wird, aber manchmal hilft es bereits, den Variablennamen zu kennen, der eine Ebene über Ihrer aufgerufenen Funktion verwendet wird.
Wie Sie sehen können, müssen Sie mit dem Dekorator den Code in der Funktion nicht ändern.
Wahrscheinlich werden Sie die Args schön drucken wollen. Ich habe den Raw-Print (und auch eine auskommentierte Print-Anweisung) in der Funktion gelassen, damit es einfacher ist, mit ihm herumzuspielen.
Das ist schön und einfach! Aber ich würde mehr Komplexität nicht stören, wenn es bedeutet, dass ich nicht jeden Variablennamen zweimal wiederholen muss: einmal als Schlüsselwort-Arg-Name und einmal als Schlüsselwort-Argumentwert. – max
Sie könnten versuchen, 'debug (** locals())' aufzurufen. –