Esto es realmente complicado. Permítanme intentar dar una respuesta más completa reutilizando this code, y la pista sobre getargspec
en la respuesta de Senthil que me activó de alguna manera. Por cierto, getargspec
está en desuso en Python 3.0 y getfullarcspec
should be used en su lugar.
Esto funciona para mí en un Python 3.1.2 ambos con una llamada explícita a la función de depuración y con el uso de un decorador:
# 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
de uso:
@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()
y grabados:
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
El decorador hace trampa un poco: ya que en wrapped
obtenemos el mismo Los argumentos como la función en sí misma no importa que encontremos e informemos el ArgSpec de wrapped
en getfunc
y debug_prt_func_args
. Este código podría embellecerse un poco, pero funciona bien ahora para los simples casos de prueba de depuración que utilicé.
Otro truco que puede hacer: Si se quite la -loop for
en getfunc
se puede ver que inspect
le puede dar el "contexto" que en realidad es la línea de código fuente en una función fue llamado.Evidentemente, este código no muestra el contenido de ninguna variable asignada a su función, pero a veces ya es útil conocer el nombre de la variable utilizada un nivel por encima de la función llamada.
Como puede ver, con el decorador no tiene que cambiar el código dentro de la función.
Probablemente querrá imprimir bastante los args. He dejado la impresión en bruto (y también una declaración de impresión comentada) en la función, así que es más fácil jugar con ella.
¡Eso es agradable y simple! Pero no me importaría más complejidad si eso significa que no tengo que repetir cada nombre de variable dos veces: una vez como nombre de la palabra clave arg, y una vez como valor del argumento de la palabra clave. – max
Puedes intentar llamar a 'debug (** locals())'. –