2012-08-29 11 views
8

Sono abbastanza nuovo per Python, e ho giocato un po 'con esso per un po' ora. Ho giocato con la funzione integrata compile(), insieme a marshal e l'integrato exec(). Ho notato alcune cose per cui non riesco a trovare le risposte. Si consideri il seguente script:Python exec() di un oggetto con codice di marshalling

#!/usr/bin/python 

def foo(): 
    print "Inside foo()..." 

def main(): 
    print "This is a simple script that should count to 10." 

    for i in range(0, 10): 
     print "This is iteration number", i 

    foo() 

if __name__ == "__main__": 
    main() 

Questo funziona bene quando viene eseguito attraverso qualcosa di simile:

with open('simple.py', 'r') as f: 
    code = f.read() 
exec code 

Tuttavia, quando viene compilato in un oggetto codice tramite compile(), serializzato via marshal.dump(), salvato in un file e poi leggere dal file, deserializzato tramite marshal.load() ed eseguito con exec(), si verifica un errore con NameError che indica che il nome globale foo non è definito.

Ho esaminato l'output fornito da dir() e quando I import() il codice, posso vedere che ha una definizione per foo(). Ho anche notato che con l'utilizzo dis.dis() sul codice oggetto deserializzato (letto tramite marshal.load()), l'unica cosa che vedo è il LOAD_NAME e CALL_FUNCTION per main() (al contrario di fare qualcosa di simile exec 'import %s' % modname, e poi facendo dis.dis(sys.modules[modname]), che ti dà l'intero smontaggio come previsto).

Sono corretto che esiste una sorta di tabella di ricerca che consente a import() di consultare questi indirizzi? (Per la cronaca, ho controllato http://svn.python.org/projects/python/trunk/Lib/py_compile.py e le uniche differenze che ho potuto vedere nel bytecode che è stato generato tramite py_compile.compile() e l'compile() integrato era il imp.get_magic(), insieme al timestamp a 32 bit). Se esiste un tale tavolo, c'è un buon modo per consultarlo?

Grazie!

+1

quando viene serializzato tramite 'marshal.dump()'? il file di testo? – Claudiu

+0

L'oggetto codice per quello script generato tramite 'compile()'. – user1633448

+0

Cosa intendi? Quanto segue sembra funzionare: con open ('simple.py', 'r') come f: code = f.read() con open ('simple.mash', 'w') come f: marshal.dump (codice, f) con aperta ('simple.mash', 'r') come f: codice = marshal.load (f) codice exec – Dhara

risposta

0

Questo script esegue correttamente il codice simple.py 3 volte. Questo chiarisce qualcosa? O sto fraintendendo la tua domanda?

# from original example 
with open('simple.py', 'r') as f: 
    code = f.read() 
exec(code) 
# compile and run again 
a = compile(code, "simple_compiled_this_file_not_created", "exec") 
exec(a) 
# marshal and unmarshal 
import marshal 
f = open("./marshalfoo.bin", "wb") 
marshal.dump(a,f) 
f.close() 
b = marshal.load(open("./marshalfoo.bin", "rb")) 
exec(b) 
+1

Interessante. Quindi sono stato in grado di rintracciare il mio problema in base al tuo codice. Sembrerebbe che se provo a 'exec()' il codice dall'interno di una funzione, fallisce (ad esempio dopo essere stato eseguito in 'compile()' chiamo una funzione che ho creato chiamata 'runme()' che in realtà chiama 'exec() 'sull'oggetto codice risultante). Ciò che è ancora più interessante è che se chiamo 'exec()' dallo stesso scope di 'compile()' e poi chiamo 'runme()' è che funziona bene. Quindi è sicuramente un problema di scoping. – user1633448

+1

Per chi se ne importa, ho fatto in modo che tutto funzioni come previsto inserendo il codice all'interno di simple.py all'interno di una classe personalizzata (l'ho chiamato Simple), quindi in "if __name__ ==" __main __ "' doing' s = Simple() 'e' s.main() '. Dopo che il codice sembra funzionare bene da qualsiasi ambito. – user1633448

Problemi correlati