Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I print the variable arguments with names from previous stack?

Tags:

python

inspect

I would like to define a log function that is called with a message followed by one or more variables to be printed out. So, something like the following:

log( "Oh no, error.", x, d)

log would be defined sorta like:

def log( msg, *arg):
    # Loop through arg, printing caller's variable's name and value.

This would log to a file the following:

Oh no, error.
    x = 5
    d = { foo: "Foo", goo: "Goo" }

Can this be done at all? I can print locals and arguments using inspect, but I don't know if I can iterate through values in the current frame, using the variable names of a previous frame. (locals in inspect.getargvalues(previousFrame) has the names, but lots of other names too.)

like image 505
Bitdiot Avatar asked Sep 15 '15 16:09

Bitdiot


People also ask

How can we handle a variable number of parameters in Python?

You can use *args as a non-keyword argument. You will then be able to pass any number of arguments. As you can see, Python will unpack the arguments as a single tuple with all the arguments.

What is varargs in Python?

Variable-length arguments, varargs for short, are arguments that can take an unspecified amount of input. When these are used, the programmer does not need to wrap the data in a list or an alternative sequence. In Python, varargs are defined using the *args syntax.

What are variable-length arguments explain with the help of a code?

You may need to process a function for more arguments than you specified while defining the function. These arguments are called variable-length arguments and are not named in the function definition, unlike required and default arguments.


2 Answers

I think you can use something like this:

definition

def log(msg, **kwargs):
    print(msg)
    for key, value in kwargs.items():
        print('{0} = {1}'.format(key,value))

definition (if order is a must)

def log(msg, **kwargs):
    print(msg)
    for key, value in sorted(kwargs.items()):
        print('{0} = {1}'.format(key,value))

usage

msg='Oh no, error'
log(msg, x=5, y=6)

output

Oh no, error
y = 6
x = 5
like image 104
jlnabais Avatar answered Sep 22 '22 01:09

jlnabais


That could be very dirty and may not work from time to time (it does so on my machine), but it seems to do the trick.

Moreover, it doesn't need all these **keargs tricks. You just call log('Message',as,many,args,as,you,want) and that's all.

import inspect, gc

def log(msg,*args):
    #This gets the source code line that has to do with args
    #I mean, that calls log
    code=''.join(inspect.getframeinfo(gc.get_referrers(args)[0].f_back).code_context).strip()
    #get the arguments (except msg)
    c=code.split('log')[1].strip()
    c=c.replace('(','').replace(')','')
    c=c.split(',')[1:]
    if c[-1].endswith(';'):
        c[-1]=c[-1].replace(';','')

    for x in xrange(0,len(c)):
        print c[x],'=',args[x]


a=5; b='hello'

print 'test'

log('hello',a,b);

print 'hello'

Even if log is run from another function, it's OK.

like image 42
ForceBru Avatar answered Sep 25 '22 01:09

ForceBru