Skip to content Skip to sidebar Skip to footer

Printing Names Of Variables Passed To A Function

In some circumstances, I want to print debug-style output like this: # module test.py def f() a = 5 b = 8 debug(a, b) # line 18 I want the debug function to print the follow

Solution 1:

You could do something along the following lines:

import inspect

defdebug(**kwargs):
  st = inspect.stack()[1]
  print'%s:%d %s()' % (st[1], st[2], st[3])
  for k, v in kwargs.items():
    print'%s = %s' % (k, v)

deff():
  a = 5
  b = 8
  debug(a=a, b=b) # line 12

f()

This prints out:

test.py:12 f()
a = 5
b = 8

Solution 2:

You're generally doing it right, though it would be easier to use AOP for this kinds of tasks. Basically, instead of calling "debug" every time with every variable, you could just decorate the code with aspects which do certain things upon certain events, like upon entering the function to print passed variables and it's name.

Please refer to this site and old so post for more info.

Solution 3:

Yeah, you are in the correct track. You may want to look at inspect.getargspec which would return a named tuple of args, varargs, keywords, defaults passed to the function.

import inspect

deff():
  a = 5
  b = 8
  debug(a, b)


defdebug(a, b):
    print inspect.getargspec(debug)
f()

Solution 4:

This is really tricky. Let me try and give a more complete answer reusing this code, and the hint about getargspec in Senthil's answer which got me triggered somehow. Btw, getargspec is deprecated in Python 3.0 and getfullarcspec should be used instead.

This works for me on a Python 3.1.2 both with explicitly calling the debug function and with using a decorator:

# from: https://stackoverflow.com/a/4493322/923794defgetfunc(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])


defdebug_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 herereturn func_name



defdf_dbg_prt_func_args(f):
    """Decorator: dpg_prt_func_args - Prints function name and arguments

    """defwrapped(*args, **kwargs):
        debug_prt_func_args(f) 
        return f(*args, **kwargs) 
    return wrapped

Usage:

@df_dbg_prt_func_argsdefleaf_decor(*args, **kwargs):
    """Leaf level, simple function"""print("in leaf")


defleaf_explicit(*args, **kwargs):
    """Leaf level, simple function"""
    debug_prt_func_args()
    print("in leaf")


defcomplex():
    """A complex function"""print("start complex")
    leaf_decor(3,4)
    print("middle complex")
    leaf_explicit(12,45)
    print("end complex")


complex()

and prints:

start complex
debug info at debug.py: 54
leaf_decor:ArgInfo(args=[], varargs='args', keywords='kwargs', locals={'args': (3, 4), 'f': <functionleaf_decorat 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

The decorator cheats a bit: Since in wrapped we get the same arguments as the function itself it doesn't matter that we find and report the ArgSpec of wrapped in getfunc and debug_prt_func_args. This code could be beautified a bit, but it works alright now for the simple debug testcases I used.

Another trick you can do: If you uncomment the for-loop in getfunc you can see that inspect can give you the "context" which really is the line of source code where a function got called. This code is obviously not showing the content of any variable given to your function, but sometimes it already helps to know the variable name used one level above your called function.

As you can see, with the decorator you don't have to change the code inside the function.

Probably you'll want to pretty print the args. I've left the raw print (and also a commented out print statement) in the function so it's easier to play around with.

Post a Comment for "Printing Names Of Variables Passed To A Function"