2012-10-02 14 views

Respuesta

20

eval evalúa cosas como 5+3

exec ejecuta cosas por el estilo for ...

>>> eval("for x in range(3):print x") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<string>", line 1 
    for x in range(3):print x 
    ^
SyntaxError: invalid syntax 
>>> exec("for x in range(3):print x") 
0 
1 
2 
>>> eval('5+3') 
8 
+0

Vaya. Tu respuesta estuvo aquí! Debería haber marcado eso como dupe: P –

+0

jaja Me olvidé de todo esto: P –

+0

Lo capté desde aquí http: // stackoverflow.com/questions/30671563/eval-not-working-on-multi-line-string # comment49405263_30671563: D –

11

Para utilizar este tipo de declaraciones con eval debe convertirlos en objeto de código en primer lugar, el uso de compile():

In [149]: import os 

In [150]: cc = compile('''for index in range(10): 
    os.system("echo " + str(index) + "")''','abc','single') 

In [154]: eval cc 
--------> eval(cc) 
0 
Out[154]: 0 
1 
Out[154]: 0 
2 
Out[154]: 0 
3 
Out[154]: 0 
4 

In [159]: cc = compile("2+2", 'abc', 'single') # works with simple expressions too 

In [160]: eval cc 
--------> eval(cc) 
Out[160]: 4 


>>> help(compile) 

compile(...) 
    compile(source, filename, mode[, flags[, dont_inherit]]) -> code object 

    Compile the source string (a Python module, statement or expression) 
    into a code object that can be executed by the exec statement or eval(). 
    The filename will be used for run-time error messages. 
    The mode must be 'exec' to compile a module, 'single' to compile a 
    single (interactive) statement, or 'eval' to compile an expression. 
    The flags argument, if present, controls which future statements influence 
    the compilation of the code. 
    The dont_inherit argument, if non-zero, stops the compilation inheriting 
    the effects of any future statements in effect in the code calling 
    compile; if absent or zero these statements do influence the compilation, 
    in addition to any features explicitly specified. 
+2

como siempre una buena respuesta y una característica de python que no conocía :) –

5

Evaluamos (eval) expresiones y ejecutamos (exec) instrucciones.

Ver: Expression Versus Statement.

Expression: Something which evaluates to a value. Example: 1+2/x
Statement: A line of code which does something. Example: GOTO 100

2

(Ver la advertencia de seguridad por defecto al final antes de poner código como este en producción!)

Las otras respuestas hacen un buen trabajo de explicar la diferencia entre exec y eval.

Sin embargo, me encontré que quieran tomar la entrada como x=1; y=2; x+y en lugar de forzar a la gente escriben: la manipulación

def f(): 
    x = 1 
    y = 2 
    return x + y 

cadena de código para construir este tipo de función es un negocio arriesgado.

Terminé usando el siguiente enfoque:

def multiline_eval(expr, context): 
    "Evaluate several lines of input, returning the result of the last line" 
    tree = ast.parse(expr) 
    eval_expr = ast.Expression(tree.body[-1].value) 
    exec_expr = ast.Module(tree.body[:-1]) 
    exec(compile(exec_expr, 'file', 'exec'), context) 
    return eval(compile(eval_expr, 'file', 'eval'), context) 

Este analiza el código Python; usa la biblioteca ast para reconstruir un ast de todo aparte de la última línea; y la última línea, que exime a la primera y evalúa la posterior.

advertencia de seguridad

Esta es la advertencia de seguridad obligatorio que tiene que adjuntar a eval. Eval 'ing y exec' El código proporcionado por un usuario no privilegiado es, por supuesto, inseguro. En estos casos, es posible que prefiera utilizar otro enfoque, o considere ast.literal_eval. eval y exec tienden a ser malas ideas a menos que realmente desee darle a su usuario el poder expresivo completo de python.

Cuestiones relacionadas