Domanda

Sembra che siano stati cancellati in Python 3 in modo semplice per caricare rapidamente uno script rimuovendo execfile ()

C'è un'alternativa ovvia che mi manca?

È stato utile?

Soluzione

Secondo la documentazione , anziché

execfile("./filename") 

Usa

exec(open("./filename").read())

See:

Altri suggerimenti

Devi solo leggere il file ed eseguire il codice da solo. 2to3 sostituisce attualmente

execfile("somefile.py", global_vars, local_vars)

come

with open("somefile.py") as f:
    code = compile(f.read(), "somefile.py", 'exec')
    exec(code, global_vars, local_vars)

(La chiamata di compilazione non è strettamente necessaria, ma associa il nome file all'oggetto codice rendendo il debug un po 'più semplice.)

See:

Mentre exec (open (" nomefile "). read ()) viene spesso fornito in alternativa a execfile (" nomefile ") , manca importante dettagli supportati da execfile .

La seguente funzione per Python3.x è la più vicina possibile allo stesso comportamento dell'esecuzione diretta di un file. Corrisponde all'esecuzione di python /path/to/somefile.py .

def execfile(filepath, globals=None, locals=None):
    if globals is None:
        globals = {}
    globals.update({
        "__file__": filepath,
        "__name__": "__main__",
    })
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), globals, locals)

# execute the file
execfile("/path/to/somefile.py")

Note:

  • Utilizza la lettura binaria per evitare problemi di codifica
  • Garantito per chiudere il file (Python3.x lo avverte)
  • Definisce __main__ , alcuni script dipendono da questo per verificare se si stanno caricando come modulo o no per es. se __name__ == " __ main __ "
  • L'impostazione di __file__ è migliore per i messaggi di eccezione e alcuni script usano __file__ per ottenere i percorsi di altri file relativi a loro.
  • Prende globali & amp; opzionali argomenti locali, modificandoli sul posto come execfile , in modo da poter accedere a qualsiasi variabile definita leggendo nuovamente le variabili dopo l'esecuzione.

  • A differenza del execfile di Python2, questo non modifica lo spazio dei nomi corrente per impostazione predefinita. Per questo devi passare esplicitamente in globals () & amp; locals () .

Come suggerito sulla mailing list python-dev recentemente, il modulo runpy potrebbe essere una valida alternativa. Citando da quel messaggio:

  

https://docs.python.org/3/library/ runpy.html # runpy.run_path

import runpy
file_globals = runpy.run_path("file.py")

Esistono sottili differenze con execfile :

  • run_path crea sempre un nuovo spazio dei nomi. Esegue il codice come modulo, quindi non c'è differenza tra globali e locali (motivo per cui esiste solo un argomento init_globals ). I globi vengono restituiti.

    execfile eseguito nello spazio dei nomi corrente o nello spazio dei nomi indicato. La semantica di locals e globals , se fornita, era simile a quella di local e globals all'interno di una definizione di classe.

  • run_path può non solo eseguire file, ma anche uova e directory (fare riferimento alla sua documentazione per i dettagli).

Questo è meglio, dal momento che prende i globali e i locali dal chiamante:

import sys
def execfile(filename, globals=None, locals=None):
    if globals is None:
        globals = sys._getframe(1).f_globals
    if locals is None:
        locals = sys._getframe(1).f_locals
    with open(filename, "r") as fh:
        exec(fh.read()+"\n", globals, locals)

Puoi scrivere la tua funzione:

def xfile(afile, globalz=None, localz=None):
    with open(afile, "r") as fh:
        exec(fh.read(), globalz, localz)

Se davvero dovevi ...

Se lo script che desideri caricare si trova nella stessa directory di quella che esegui, forse " import " farà il lavoro?

Se devi importare dinamicamente il codice la funzione integrata __ import __ e il modulo imp merita una visita.

>>> import sys
>>> sys.path = ['/path/to/script'] + sys.path
>>> __import__('test')
<module 'test' from '/path/to/script/test.pyc'>
>>> __import__('test').run()
'Hello world!'

test.py:

def run():
        return "Hello world!"

Se usi Python 3.1 o versioni successive, dovresti anche dare un'occhiata a importlib .

Ecco cosa avevo ( file è già assegnato al percorso del file con il codice sorgente in entrambi gli esempi):

execfile(file)

Ecco cosa l'ho sostituito con:

exec(compile(open(file).read(), file, 'exec'))

La mia parte preferita: la seconda versione funziona perfettamente in Python 2 e 3, il che significa che non è necessario aggiungere una logica dipendente dalla versione.

Nota che il modello sopra fallirà se stai usando le dichiarazioni di codifica PEP-263 che non sono ascii o utf-8. Devi trovare la codifica dei dati e codificarla correttamente prima di consegnarlo a exec ().

class python3Execfile(object):
    def _get_file_encoding(self, filename):
        with open(filename, 'rb') as fp:
            try:
                return tokenize.detect_encoding(fp.readline)[0]
            except SyntaxError:
                return "utf-8"

    def my_execfile(filename):
        globals['__file__'] = filename
        with open(filename, 'r', encoding=self._get_file_encoding(filename)) as fp:
            contents = fp.read()
        if not contents.endswith("\n"):
            # http://bugs.python.org/issue10204
            contents += "\n"
        exec(contents, globals, globals)

Inoltre, pur non essendo una soluzione Python pura, se stai usando IPython (come probabilmente dovresti comunque), puoi fare:

%run /path/to/filename.py

Il che è altrettanto facile.

Sono solo un principiante qui, quindi forse è pura fortuna se lo trovassi:

Dopo aver provato a eseguire uno script dal prompt dell'interprete > > > con il comando

    execfile('filename.py')

per il quale ho ricevuto un " NameError: il nome 'execfile' non è definito " Ho provato un

molto semplice
    import filename

ha funzionato bene :-)

Spero che questo possa essere utile e grazie a tutti per i grandi suggerimenti, esempi e tutti quei pezzi di codice commentati magistralmente che sono di grande ispirazione per i nuovi arrivati!

Uso Ubuntu 16.014 LTS x64. Python 3.5.2 (impostazione predefinita, 17 novembre 2016, 17:05:23) [GCC 5.4.0 20160609] su Linux

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top