2009-07-06 33 views
22

Hay una función eval() en Python que tropecé mientras jugaba. No puedo pensar en un caso cuando se necesita esta función, excepto tal vez como azúcar sintáctico. ¿Alguien puede dar un ejemplo?Uso de eval en Python?

+1

'como azúcar sintáctico' - ¿qué significa esto? – jwg

Respuesta

39

eval y exec son manera rápida y sucia-práctico para conseguir un poco de código fuente de forma dinámica, tal vez munge un poco, y luego ejecutarlo - pero son rara vez la mejor manera, especialmente en la producción código en comparación con los prototipos "rápidos y sucios" & c.

Por ejemplo, si tuviera que hacer frente a tales fuentes de Python dinámicos, me gustaría llegar para el módulo ast-ast.literal_eval es mucho más seguro que eval (se le puede llamar directamente en una forma de cadena de la expresión, si se trata de una única vez y solo se basa en constantes simples, o node = ast.parse(source) primero, luego guarde el node, quizás enviándolo con visitantes adecuados, por ejemplo, para búsqueda variable, luego literal_eval el nodo) o, una vez que haya puesto el nodo en la forma adecuada y lo revisé por cuestiones de seguridad, pude compile (produciendo un objeto de código) y crear un nuevo objeto de función a partir de eso. Mucho menos simple (excepto que ast.literal_eval es tan simple como eval para los casos más simples!) Pero más seguro y preferible en código de calidad de producción.

Para muchas tareas que he visto personas (AB) utilizan exec y eval para, potentes muebles empotrados de Python, como getattr y setattr, indexación en globals(), & C, proporcionan soluciones simples a menudo preferibles y de facto. Para usos específicos como el análisis de JSON, los módulos de biblioteca como json son mejores (por ejemplo, vea el comentario de SilentGhost sobre la respuesta de tinnitus a esta pregunta). Etc, etc ...

15

El Wikipedia article on eval es bastante informativo y detalla varios usos.

Algunos de los usos que sugiere son:

  • Evaluación de expresiones matemáticas
  • Compiler bootstrapping
  • Scripting (lenguajes dinámicos, en general, son muy adecuados para esto)
  • tutores del idioma
+0

Miré este artículo y aún no entiendo ... ¡Esto es más como una función de cálculo que calcula una expresión aritmética! – ooboo

+1

@ooboo: 'eval' puede ejecutar * cualquier * código en teoría (de ahí los riesgos de seguridad señalados en el artículo). – Noldorin

1

eval() normalmente no es muy útil. Una de las pocas cosas para las que lo he usado (bueno, era exec() en realidad, pero es bastante similar) le estaba permitiendo al usuario crear un script para una aplicación que escribí en Python. Si estuviera escrito en algo como C++, tendría que incrustar un intérprete de Python en la aplicación.

3

En un programa de I escribió una vez, que tenía un archivo de entrada donde se puede especificar los parámetros geométricos tanto como valores y como expresiones pitón de los valores anteriores, por ejemplo:

a=10.0 
b=5.0 
c=math.log10(a/b) 

Un analizador pitón leer este archivo de entrada y obtuve los datos finales evaluando los valores y las expresiones usando eval().

No pretendo que sea una buena programación, pero no tuve que conducir un reactor nuclear.

5

En el pasado he utilizado eval() para agregar una interfaz de depuración a mi aplicación. Creé un servicio de telnet que lo llevó al entorno de la aplicación en ejecución. Las entradas se ejecutaron a través de eval() para que pueda ejecutar de manera interactiva los comandos de Python en la aplicación.

+0

He hecho secuencias de comandos similares a la interfaz COM para Enterprise Architect para probar diferentes consultas –

13

Es posible que desee utilizarlo para permitir a los usuarios introducir sus propios "scriptles": pequeñas expresiones (o incluso funciones pequeñas), que se puede utilizar para personalizar el comportamiento de un sistema complejo .
En ese contexto, y si no tiene que preocuparse demasiado por las implicaciones de seguridad (por ejemplo, tiene una base de usuarios educada), entonces eval() puede ser una buena opción.

1

Eval es una forma de interactuar con el intérprete de Python desde un programa. Puede pasar literales a eval y los evalúa como expresiones de pitón.

Por ejemplo -

print eval("__import__('os').getcwd()") 

devolvería el directorio de trabajo actual.

aplausos

+0

buena idea también :) – securecurve

1

lo uso como un analizador JSON rápida ...

r=''' 
{ 
    "glossary": { 
     "title": "example glossary" 
     } 
} 
''' 

print eval(r)['glossary']['title'] 
+10

no lo hagas. 'eval (" "" {"glossary": {"death": false}} "" ")' -> 'NameError: name 'false' no está definido' – SilentGhost

+0

@SilentGhost: ese es un gran punto, lo he usó su ejemplo en una respuesta a una pregunta; http://stackoverflow.com/questions/1083250/running-json-through-pythons-eval/1083302 – Kiv

+1

El uso de un analizador * JSON * real sería menos problemático y más seguro. –

-1

Uso exec para crear un sistema de complementos en Python.

 
    try: 
     exec ("from " + plugin_name + " import Plugin") 
     myplugin = Plugin(module_options, config=config) 
    except ImportError, message: 
     fatal ("No such module " + plugin_name + \ 
       " (or no Plugin constructor) in my Python path: " + str(message)) 
    except Exception: 
     fatal ("Module " + plugin_name + " cannot be loaded: " + \ 
       str(sys.exc_type) + ": " + str(sys.exc_value) + \ 
       ".\n May be a missing or erroneous option?") 

Con un plugin como:

 
class Plugin: 

    def __init__ (self): 
     pass 

    def query(self, arg): 
     ... 

Podrá llamarlo como:

 
    result = myplugin.query("something") 

no creo que puede tener plugins en Python sin exec/eval.

+3

Esto no es bueno. Debe utilizar la función incorporada '__import__', que recibe el nombre de la instrucción' from ... import ... '. – gahooa

0

que lo utilizaron para valores de las variables de entrada al programa principal:

test.py var1 var2 = 2 = True

...

var1=0 
var2=False 
for arg in sys.argv[1:]: 
    exec(arg) 

Una forma cruda para permitir argumentos de palabras clave en el programa principal. Si hay una mejor manera házmelo saber!

0

eval() es para una sola oración, mientras que exec() es para varias.

generalmente los usamos para agregar o visitar algunos scripts como bash shell.

porque pueden ejecutar algunos scripts de bytes en la memoria, si tiene datos importantes o secuencias de comandos puede decodificar y descomprimir su "secreto" y luego hacer todo lo que quiera.

0

Acabo de encontrar un buen uso de eval. Estaba escribiendo un banco de pruebas para algún código, y creé una clase de prueba, donde cada método era una prueba para ejecutar.Quería una manera para poder ejecutar todos los métodos de prueba sin tener que llamar a cada método individualmente. Entonces, escribí algo bastante sucio.

class Test: 
    def __init__(self, *args): 
     #bs 

    def test1(self): 
     #bs 

    def test2(self): 
     #bs 

if __name__ == "__main__": 
    import argparse 
    #argparse bs 
    test = Test(*bs_args) 
    for func in (i for i in dir(test) if i[0] != '_' and i not in test.__dict__): 
     print(eval('test.{func}()'.format(func = func))) 

La evaluación dinámica de casos de prueba arbitrarios es muy buena. Solo tengo que escribir el método, y después de guardar puedo incluir el método en mi suite de pruebas. En cuanto al código, básicamente inspecciono los métodos definidos en el objeto de prueba y me aseguro de que no sean métodos o atributos "mágicos" predeterminados de Python para el objeto Test. Después de eso, puedo asumir que son métodos y que pueden evaluarse.

0

Puede utilizar eval en un decorador:

#this replaces the original printNumber with a lambda-function, 
#which takes no arguments and which calls the old function with 
#the number 10 
@eval("lambda fun: lambda: fun(10)") 
def printNumber(i: int) -> None: 
    print("The number is %i", i) 

#call 
printNumber() 

mientras que no se puede utilizar expresiones complejas como

@lambda fun: lambda: fun(10) 
def ... 

ni

@(lambda fun: lambda: fun(10)) 
def ... 

No se puede utilizar un lambda-expresión allí, porque el decorador debe ser un identificador:

@myModule.functionWithOneArg 

o una llamada de función:

@functionReturningFunctionWithOneArg(any, "args") 

se ve que la llamada de la función eval con una cadena tiene una sintaxis válida aquí, pero el lambda-expresión no. (->https://docs.python.org/3/reference/compound_stmts.html#function-definitions)