2012-11-12 11 views
5

Ho bisogno di compilare una stringa di input (da un database) come una funzione ed eseguirla. Questo è il metodo che attualmente uso:Come compilare il testo come una funzione usando AST?

dire che ho già ho questa funzione definita:

def foo(): 
    print "Yo foo! I am a function!" 

E la stringa ho letto dal database dice che dovrei chiamare questa funzione:

string_from_db = "foo()" 

Quindi formulo una funzione (il cui nome posso controllare) che restituisce la funzione che ho letto dal database:

my_func_string = "def doTheFunc():\n\t return " + string_from_db 

Ora posso compilare la corda, e impostarlo su un nome di funzione che uso in seguito per l'elaborazione:

exec my_func_string 
processor = doTheFunc 

posso chiamare successivamente lanciando processor() che esclama: Yo foo! I am a function!

La mia domanda: Sopra questo pezzo di codice v'è un commento (lasciato da uno sviluppatore a lungo perduto): "sostituzione potenziale"

############################################################### 
    # The following method for getting a function out of the text # 
    # in the database could potentially be replaced by using  # 
    # Python's ast module to obtain an abstract syntax tree and # 
    # put it inside of a function node       # 
    ############################################################### 

mi piacerebbe sapere di più su questo Ho dato un'occhiata a AST, ma sono molto confuso su come può aiutarmi a fare quello che sto già facendo con il codice sopra.

  1. Come posso ottenere la stessa cosa utilizzando AST? O dove può AST aiutarmi in questo processo?
  2. L'implementazione utilizza AST meglio e perché?
+5

Sii nei regni della magia oscura. –

+1

Se si conoscono le stringhe per essere sicuri, non c'è motivo di usare 'ast' su' exec() '. L'interprete Python implementa già l'analisi del codice sorgente Python in oggetti funzione, perché replicarlo? – millimoose

+0

@millimoose Ho finito con l'implementazione di 'exec', perché so che le mie corde sono sicure. Tuttavia, questa domanda mi ha illuminato su usi migliori per 'ast'. Grazie! – dinkelk

risposta

5

AST è una scelta molto più sicuro quando si valuta il codice non attendibile, che potrebbe contenere le istruzioni dannosi, eval o exec in grado di eseguire qualsiasi espressione, mentre AST d'altra parte, consente di analizzare e convalidare l'espressione da soli, o eseguire un'espressione limitata usando ast.literal_eval, un po 'come una sandbox, che consente solo stringhe, liste, numeri e poche altre cose. Questo è solo un semplice esempio:

import ast 
a = ast.literal_eval("[1,2,3,4]") //evaluate an expression safely. 

Un altro esempio che analizza una stringa in un AST:

import ast 
source = '2 + 2' 
node = ast.parse(source, mode='eval') 
ast.dump(node) 

Questo stampa:

Expression(body=BinOp(left=Num(n=2), op=Add(), right=Num(n=2))) 

C'è un ottimo tutorial here e anche il documentation

+0

Grande tutorial! Come potrei fare per "convalidare un'espressione per me stesso"? Come posso sapere se il codice è cattivo o non soddisfa i miei requisiti? Supponendo che avrò bisogno di compilare piccole funzioni; Non posso limitarmi a semplici stringhe, liste, ecc. – dinkelk

+0

@babydanks puoi scoprire se chiama qualsiasi funzione che non dovrebbe, come 'open' forse. – iabdalkader

+0

Ah! A che livello è più facile da fare? Una volta che hai un nodo funzione ast? (ad esempio, quale sarebbe il modo più semplice per verificare la presenza di 'open'?) – dinkelk

Problemi correlati