Pasar una lista a eval ()
Pregunta
¿Hay alguna forma de pasar una lista como argumento de función a eval () O tengo que convertirla en una cadena y luego analizarla como una lista en la función?
Mi ejemplo simple se ve así:
eval("func1(\'" + fArgs + "\')")
Simplemente no estoy seguro de si hay una mejor manera de tomar fArgs como una lista en lugar de una cadena
Nota: La lista se proporciona a partir de una respuesta JSON
EDITAR: Ok, aquí hay un poco más de mi clase, así que hay una mejor comprensión de cómo estoy usando 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)
Puedo estar equivocado al pensar esto, pero a mi entender, este es un uso seguro de eval porque las únicas funciones que se pueden invocar son las que se enumeran en el diccionario safe_list. La función a ejecutar y los argumentos para esa función se extraen de un objeto JSON. Los argumentos deben estructurarse como una lista. Se unirá a la lista junto con " ;, " ser interpretado como argumentos reales o simplemente como un solo argumento?
Solución
Si está usando Python 2.6.x, entonces debería poder usar el módulo json
(vea py doc 19.2 ). Si no, entonces hay python-json disponible a través del índice del paquete python. Ambos paquetes proporcionarán un lector para analizar datos JSON en un tipo de datos Python apropiado.
Para su segundo problema de llamar a una función determinada por un mensaje, puede hacer lo siguiente:
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']()
Este enfoque puede ser un poco más seguro que eval
porque evita que las funciones de la biblioteca de Python 'inseguras' se inyecten en el JSON. Sin embargo, aún debe tener cuidado de que los datos suministrados a sus funciones no puedan manipularse para causar problemas.
Otros consejos
Especificar parámetros de la siguiente manera funciona:
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
entonces, no hay necesidad directa de eval (), a menos que esté malinterpretando algo.
Usar una biblioteca para analizar la entrada JSON puede ser un mejor enfoque que eval, algo como:
import json
func1(json.loads(fArgs))
Afirmar que la entrada del usuario es correcta también sería una buena idea.
Los otros tienen un buen punto, que no deberías usar eval
. Pero, si debes:
eval("func1(%s)" % ", ".join(fArgs))
llamará a la función con todos los argumentos en la lista. Esto:
eval("func1([%s])" % ", ".join(fArgs))
lo llamará con la lista de argumentos en un solo argumento. ¿Quizás incluso quieres esto?
eval("func1([%s])" % ", ".join(map(eval, fArgs)))
¿cuál eval
también los argumentos?