2013-07-27 7 views
7

Guardando attraverso l'elenco delle funzioni Python built-in, faccio fatica a capire l'utilità del metodo compile. Tutti gli esempi che ho trovato indicano un semplice "ciao mondo". Ha senso cosa fa, ma non quando per usarlo.Qual è l'uso principale di Python integrato in "compilazione"?

È lo stesso metodo utilizzato da Python per generare i file .pyc?

Può essere utilizzato per rimuovere parte della natura dinamica di Python per migliorare le prestazioni su determinati blocchi di codice? (Ben sapendo che un modulo in C è la strada da percorrere moduli precompilate.)

risposta

6

Da qui: What's the difference between eval, exec, and compile in Python?:

compile è una versione di livello inferiore e execeval. Non esegue o valuta le tue dichiarazioni o espressioni, ma restituisce un oggetto codice che può farlo. Le modalità sono le seguenti:

  1. compile(string, '', 'eval') restituisce il codice oggetto che sarebbe stato eseguito se aveste fatto eval(string). Si noti che è impossibile utilizzare le istruzioni in questa modalità; solo una (singola) espressione è valida.
  2. compile(string, '', 'exec') restituisce l'oggetto codice che sarebbe stato eseguito se l'utente avesse eseguito exec(string). Puoi usare qualsiasi numero di dichiarazioni qui.
  3. compile(string, '', 'single') è come la modalità exec, ma ignorerà tutto tranne la prima istruzione. Si noti che una dichiarazione if/else con i relativi risultati è considerata una singola istruzione.

UPDATE:

Quando per compilare Python?

Generalmente si compila Python per sfruttare le prestazioni. Il codice compilato ha un tempo di avvio molto più veloce poiché non deve essere compilato, ma non viene eseguito più rapidamente.

In particolare, è possibile utilizzare compile se si desidera convertire il codice in bytecode a mano. Questo fa emergere un'altra importante, ma pertinente domanda perché fare questo?

Come riferimento in questo magnificent article:

se si desidera utilizzare exec e si prevede di eseguire il codice più di una volta, assicurarsi che si compila in bytecode prima e quindi eseguire che bytecode solo ed solo in un nuovo dizionario come spazio dei nomi.

Di particolare nota è questo:

Ora quanto più veloce è l'esecuzione di bytecode sulla creazione di bytecode e l'esecuzione di questo?:

$ python -mtimeit -s 'code = "a = 2; b = 3; c = a * b"' 'codice exec' 10000 cicli, migliore di 3: 22,7 usec per loop

$ python -mtimeit -s 'code = compile ("a = 2; b = 3; c = a * b",
"", "exec")' 'codice exec' 1000000 loop, meglio di 3: 0.765 usec per loop

32 volte più veloce per un esempio di codice molto breve. Diventa molto peggio più codice hai. Perché è così? Poiché l'analisi del codice Python e la conversione in Bytecode è un'operazione costosa rispetto alla valutazione del bytecode. Ovviamente questo riguarda anche lo execfile che non utilizza totalmente cache bytecode, come dovrebbe. Non verificherà magicamente se esiste un file .pyc se si è passando il percorso a un file foo.py.

+0

Questo è quello che ho raccolto da ciò che fa, ma non è ancora chiaro quando/perché per usarlo. L'unica cosa che viene in mente sarebbe un rapido controllo per vedere se ci sono errori di sintassi prima di chiamare un 'eval'/'exec'. –

+0

@AdamLewis, mi scuso. Aggiornato. – jrd1

+1

Grande aggiornamento. Avevo l'impressione che fosse orientato solo a essere davvero utile quando si usava il built-in di 'exec'. Grazie per aver dedicato del tempo a far luce sull'argomento. –

2

Per rispondere alla natura dinamica, no, non proprio. L'oggetto codice risultante è ancora interpretato; lo stesso bytecode è ancora in esecuzione.

L'uso più utile/impressionante di compilazione() (e generazione di codice) che ho visto è in Jinja2. Genera effettivamente il codice Python dai tuoi template, quindi usa la compilazione in modo che funzioni a velocità 'nativa' (== interpreter), se questo ha senso.

https://github.com/mitsuhiko/jinja2/blob/master/jinja2/environment.py#L506

In contrasto con, diciamo, django.template, che fa ricerche variabili, ecc in "userspace" (di nuovo, per così dire - la metafora è un po 'strano).

https://github.com/django/django/blob/master/django/template/base.py#L752

+0

Ho usato entrambi django e jinja, ma non ho mai scavato così profondamente nel sistema di template prima. Sono d'accordo che è un bel modo per elaborare i modelli. Forse questo è parte del motivo per cui ho usato jinga come sistema di template in django :) –

Problemi correlati