2012-10-02 9 views

risposta

20

eval valuta le cose come 5+3

exec esegue roba come 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

Oops. La tua risposta era qui! Dovrei averlo contrassegnato come dupe: P –

+0

lol Mi sono dimenticato di tutto questo: P –

+0

Ho preso questo da qui http: // StackOverflow.it/questions/30671563/eval-not-working-on-multi-line-string # comment49405263_30671563: D –

11

Per utilizzare tali dichiarazioni con eval si dovrebbe convertirli in codice oggetto prima, utilizzando 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

come sempre una buona risposta e una funzionalità di python non ne ero a conoscenza :) –

5

Valutiamo (eval) espressioni ed eseguiamo dichiarazioni (exec).

Vedere: 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

(Vedi avviso di protezione di default alla fine prima di mettere il codice come questo in produzione!)

Le altre risposte fanno un buon lavoro di spiegare la differenza tra exec e eval.

Tuttavia, mi sono trovato a voler prendere in ingresso come x=1; y=2; x+y piuttosto che costringere la gente a scrivere: la manipolazione

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

stringa di codice per costruire questo tipo di funzione è un affare rischioso.

ho finito per usare il seguente approccio:

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) 

Questo analizza codice Python; usa la libreria ast per ricostruire un elemento di tutto diverso dall'ultima riga; e l'ultima riga, eseguendo la prima e valutando la successiva.

avvertimento Security

Questo è l'avviso di protezione obbligatoria che si deve allegare al eval. Eval 'it e exec' il codice fornito da un utente non privilegiato è ovviamente insicuro. In questi casi potresti preferire un altro approccio o considerare ast.literal_eval. eval ee exec tendono ad essere idee sbagliate a meno che tu non voglia effettivamente dare al tuo utente tutta la potenza espressiva di python.

Problemi correlati