Question

Is there a way to pass a list as a function argument to eval() Or do I have to convert it to a string and then parse it as a list in the function?

My simple example looks like:

 eval("func1(\'" + fArgs + "\')")

I'm just not sure if there is a better way of taking fArgs as a list instead of a string

Note: The list is provided from a JSON response

EDIT: Ok here's a bit more of my class so there's a better understanding of how I'm using eval

def test(arg):
     print arg

#Add all allowed functions to this list to be mapped to a dictionary     
safe_list = ['test']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])

class Validate:
     def __init__(self, Value, fName, fArgs):
     eval(fName + "(\'" + fArgs + "\')", {"__builtins__":None},safe_dict)

I may be wrong in thinking this, but to my understanding this is a safe use of eval because the only functions that can be called are the ones that are listed in the safe_list dictionary. The function to be run and the arguments for that function are being extracted out of a JSON object. The arguments are to be structured as a list, Will joining the list together with ", " be interpreted as actual arguments or just a single argument?

Was it helpful?

Solution

If you're using Python 2.6.x, then you should be able to use the json module (see py doc 19.2). If not, then there is python-json available through the python package index. Both of these packages will provide a reader for parsing JSON data into an appropriate Python data type.

For your second problem of calling a function determined by a message, you can do the following:

def foo():
    print 'I am foo!'
def bar():
    pass
def baz():
    pass

funcs = {'func_a':foo, 'func_b':bar, 'func_c':baz}

funcs['func_a']()

This approach can be a bit more secure than eval because it prevents 'unsafe' python library functions from being injected into the JSON. However, you still need to be cautious that the data supplied to your functions can't be manipulated to cause problems.

OTHER TIPS

Specifying parameters the following way works:

root@parrot$ more test.py
def func1(*args):
        for i in args:
                print i

l = [1,'a',9.1]
func1(*l)

root@parrot$ python test.py
1
a
9.1

so, no direct need for eval(), unless I'm misunderstanding something.

Using a library to parse JSON input may be a better approach than eval, something like:

import json
func1(json.loads(fArgs))

Assert-ing that user input is correct would be a good idea, too.

The others have a good point, that you shouldn't be using eval. But, if you must:

eval("func1(%s)" % ", ".join(fArgs))

will call the function with all the arguments in the list. This:

eval("func1([%s])" % ", ".join(fArgs))

will call it with the list of arguments in just one argument. Maybe you even want this?

eval("func1([%s])" % ", ".join(map(eval, fArgs)))

which would eval the arguments as well?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top