it-swarm.com.de

Was ist eine Alternative zu execfile in Python 3?

Es scheint, als hätten sie auf einfache Weise in Python 3) abgebrochen, um ein Skript schnell zu laden, indem execfile() entfernt wurde.

Gibt es eine offensichtliche Alternative, die ich vermisse?

311
R S

laut Dokumentation statt

execfile("./filename") 

Verwenden

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

Sehen:

340
Pedro Vagner

Sie müssen nur die Datei lesen und den Code selbst ausführen. 2to3 Strom ersetzt

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

wie

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

(Der Kompilierungsaufruf ist nicht unbedingt erforderlich, verknüpft jedoch den Dateinamen mit dem Codeobjekt, wodurch das Debuggen ein wenig vereinfacht wird.)

Sehen:

205

Während exec(open("filename").read()) häufig als Alternative zu execfile("filename") angegeben wird, fehlen wichtige Details, die execfile unterstützt.

Die folgende Funktion für Python3.x ist so ähnlich wie das direkte Ausführen einer Datei. Das stimmt mit python /path/to/somefile.py Überein.

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")

Anmerkungen:

  • Verwendet binäres Lesen, um Codierungsprobleme zu vermeiden
  • Schließt garantiert die Datei (Python3.x warnt davor)
  • Definiert __main__, Einige Skripte hängen davon ab, um zu prüfen, ob sie als Modul geladen werden oder nicht, z. if __== "__main__"
  • Das Setzen von __file__ Ist für Ausnahmemeldungen sinnvoller, und einige Skripte verwenden __file__, Um die Pfade anderer Dateien relativ zu diesen abzurufen.
  • Übernimmt optionale globale und lokale Argumente und ändert sie direkt wie execfile - so können Sie auf alle definierten Variablen zugreifen, indem Sie die Variablen nach der Ausführung zurücklesen.

  • Im Gegensatz zu Python2s execfile ändert dies standardmäßig nicht den aktuellen Namespace. Dazu müssen Sie globals() & locals() explizit übergeben.

61
ideasman42

Als empfohlen auf der Python-Dev Mailingliste könnte das Runpy Modul eine praktikable Alternative sein. Zitat aus dieser Nachricht:

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

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

Es gibt subtile Unterschiede zu execfile:

  • run_path erstellt immer einen neuen Namespace. Es führt den Code als Modul aus, sodass es keinen Unterschied zwischen Globalen und Lokalen gibt (daher gibt es nur ein init_globals Streit). Die Globals werden zurückgegeben.

    execfile wird im aktuellen Namespace oder im angegebenen Namespace ausgeführt. Die Semantik von locals und globals ähnelte, falls angegeben, den lokalen und globalen Variablen innerhalb einer Klassendefinition.

  • run_path kann nicht nur Dateien, sondern auch Eier und Verzeichnisse ausführen (Einzelheiten finden Sie in der Dokumentation).

53
Jonas Schäfer

Dieser ist besser, da er die Globals und Locals vom Anrufer übernimmt:

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)
19
Noam

Sie könnten Ihre eigene Funktion schreiben:

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

Wenn du wirklich ...

18
Evan Fosmark

Befindet sich das zu ladende Skript in demselben Verzeichnis wie das von Ihnen ausgeführte, erledigt "import" möglicherweise die Aufgabe?

Wenn Sie Code dynamisch importieren müssen, sollten Sie sich die integrierte Funktion __ import __ und das Modul imp ansehen.

>>> 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!"

Wenn Sie Python 3.1 oder höher verwenden, sollten Sie sich auch importlib ansehen.

11
ascobol

Folgendes hatte ich (file ist in beiden Beispielen bereits dem Pfad zur Datei mit dem Quellcode zugewiesen):

execfile(file)

Folgendes habe ich ersetzt:

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

Mein Lieblingsteil: Die zweite Version funktioniert sowohl in Python 2 als auch in 3, was bedeutet, dass keine versionsabhängige Logik hinzugefügt werden muss.

9
ArtOfWarfare

Beachten Sie, dass das obige Muster fehlschlägt, wenn Sie PEP-263-Codierungsdeklarationen verwenden, die nicht ASCII oder UTF-8 sind. Sie müssen die Codierung der Daten ermitteln und korrekt codieren, bevor Sie sie an exec () übergeben.

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)
5
Eric

Auch wenn es sich nicht um eine reine Python) Lösung handelt, können Sie mit IPython (wie Sie es wahrscheinlich auch tun sollten) Folgendes tun:

%run /path/to/filename.py

Welches ist genauso einfach.

3
R S

Ich bin nur ein Neuling hier, also ist es vielleicht reines Glück, wenn ich Folgendes finde:

Nach dem Versuch, ein Skript aus dem Interpreter Prompt >>> mit dem Befehl auszuführen

    execfile('filename.py')

für die ich ein "NameError: name 'execfile' ist nicht definiert" habe ich ein sehr einfaches probiert

    import filename

es hat gut funktioniert :-)

Ich hoffe, dies kann hilfreich sein und danke Ihnen allen für die tollen Hinweise, Beispiele und all die meisterhaft kommentierten Code-Teile, die eine großartige Inspiration für Newcomer sind!

Ich benutze Ubuntu 16.014 LTS x64. Python 3.5.2 (Standardeinstellung, 17. November 2016, 17:05:23) [GCC 5.4.0 20160609] unter Linux

1
Claude