Het lijkt erop dat ze in Python 3 de gemakkelijke manier hebben geannuleerd om snel een script te laden door execfile()
te verwijderen
Is er een duidelijk alternatief dat ik mis?
Antwoord 1, autoriteit 100%
Volgens de documentatie, in plaats van
execfile("./filename")
Gebruik
exec(open("./filename").read())
Zie:
Antwoord 2, autoriteit 51%
Het is de bedoeling dat je het bestand leest en de code zelf uitvoert. 2 tot 3 stroom vervangt
execfile("somefile.py", global_vars, local_vars)
als
with open("somefile.py") as f:
code = compile(f.read(), "somefile.py", 'exec')
exec(code, global_vars, local_vars)
(De compileeraanroep is niet strikt nodig, maar het associeert de bestandsnaam met het code-object waardoor debuggen een beetje makkelijker wordt.)
Zie:
- http://docs.python.org/release/ 2.7.3/library/functions.html#execfile
- http://docs.python.org/release/ 3.2.3/library/functions.html#compile
- http://docs.python.org/release/ 3.2.3/library/functions.html#exec
Antwoord 3, autoriteit 18%
Hoewel exec(open("filename").read())
vaak wordt gegeven als alternatief voor execfile("filename")
, mist het belangrijke details die execfile
ondersteund.
De volgende functie voor Python3.x komt zo dicht mogelijk in de buurt van hetzelfde gedrag als het rechtstreeks uitvoeren van een bestand. Dat komt overeen met het uitvoeren van 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")
Opmerkingen:
- Gebruikt binaire lezing om coderingsproblemen te voorkomen
- Gegarandeerd om het bestand te sluiten (Python3.x waarschuwt hiervoor)
- Definieert
__main__
, sommige scripts zijn hiervan afhankelijk om te controleren of ze als module worden geladen of niet voor bijv.if __name__ == "__main__"
- Het instellen van
__file__
is prettiger voor uitzonderingsberichten en sommige scripts gebruiken__file__
om de paden van andere bestanden ten opzichte daarvan te krijgen. -
Neemt optionele globals & locals-argumenten, door ze ter plekke aan te passen zoals
execfile
doet – zodat u toegang hebt tot alle variabelen die zijn gedefinieerd door de variabelen na het uitvoeren terug te lezen. -
In tegenstelling tot het
execfile
van Python2 wijzigt dit nietde huidige naamruimte standaard. Daarvoor moet je explicietglobals()
&locals()
.
Antwoord 4, autoriteit 16%
Zoals gesuggereerd op de python-devmailinglijst onlangs zou de module runpyeen haalbaar alternatief kunnen zijn. Citaat uit dat bericht:
https://docs.python.org/3/library/ runpy.html#runpy.run_path
import runpy file_globals = runpy.run_path("file.py")
Er zijn subtiele verschillen met execfile
:
-
run_path
maakt altijd een nieuwe naamruimte aan. Het voert de code uit als een module, dus er is geen verschil tussen globals en locals (daarom is er alleen eeninit_globals
argument). De globals worden geretourneerd.execfile
uitgevoerd in de huidige naamruimte of de opgegeven naamruimte. De semantiek vanlocals
englobals
, indien gegeven, was vergelijkbaar met locals en globals binnen een klassedefinitie. -
run_path
kan niet alleen bestanden uitvoeren, maar ook eieren en mappen (raadpleeg de documentatie voor details).
Antwoord 5, autoriteit 5%
Deze is beter, omdat het de globals en locals van de beller nodig heeft:
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)
6, Autoriteit 4%
U kunt uw eigen functie schrijven:
def xfile(afile, globalz=None, localz=None):
with open(afile, "r") as fh:
exec(fh.read(), globalz, localz)
Als je echt nodig hebt om …
7, Autoriteit 2%
Hier is wat ik had (file
is al toegewezen aan het pad naar het bestand met de broncode in beide voorbeelden):
execfile(file)
Hier is wat ik heb vervangen door:
exec(compile(open(file).read(), file, 'exec'))
Mijn favoriete onderdeel: de tweede versie werkt prima in zowel Python 2 als 3, wat betekent dat het niet nodig is om versieafhankelijke logica toe te voegen.
Antwoord 8
Houd er rekening mee dat het bovenstaande patroon zal mislukken als u PEP-263-coderingsdeclaraties gebruikt
die geen ascii of utf-8 zijn. U moet de codering van de gegevens vinden en deze coderen
correct voordat u het aan exec() overhandigt.
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)
Antwoord 9
Vermijd exec()
als je kunt. Voor de meeste toepassingen is het schoner om gebruik te maken van het importsysteem van Python.
Deze functie gebruikt ingebouwde importlib
om een bestand uit te voeren als een daadwerkelijke module:
from importlib import util
def load_file_as_module(name, location):
spec = util.spec_from_file_location(name, location)
module = util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
Gebruiksvoorbeeld
Laten we een bestand hebben foo.py
:
def hello():
return 'hi from module!'
print('imported from', __file__, 'as', __name__)
en importeer het als een gewone module:
>>> mod = load_file_as_module('mymodule', './foo.py')
imported from /tmp/foo.py as mymodule
>>> mod.hello()
hi from module!
>>> type(mod)
<class 'module'>
Voordelen
Deze aanpak vervuilt geen naamvullen of rommel met uw $PATH
, terwijl exec()
Code rechtstreeks in de context van de huidige functie uitvoeren, waardoor potentieel naambotsingen veroorzaakt. Ook, moduleattributen zoals __file__
en __name__
worden correct ingesteld en CODE-locaties worden bewaard. Dus, als u een debugger hebt bijgevoegd of als de module een uitzondering verhoogt, krijgt u bruikbare traceerbacks.
Merk op dat een klein verschil van statische invoer is dat de module wordt geïmporteerd (uitgevoerd) telkens wanneer u load_file_as_module()
uitvoert, en niet alleen één keer als bij de import
sleutelwoord.
10
Ook, terwijl niet een pure python-oplossing, als u IPYTHON (zoals u waarschijnlijk hoe dan ook gebruikt), kunt u doen:
%run /path/to/filename.py
die even eenvoudig is.
11
Ik ben hier gewoon een newbie, dus misschien is het puur geluk als ik dit heb gevonden:
Na het proberen een script uit de tolk-prompt & GT; & GT; & GT; met het commando
execfile('filename.py')
waarvoor ik een “NameError: name ‘execfile’ is notdefined” kreeg Ik probeerde een heel eenvoudige
import filename
het werkte goed 🙂
Ik hoop dat dit nuttig kan zijn en ik dank jullie allemaal voor de geweldige hints, voorbeelden en al die meesterlijk becommentarieerde stukjes code die een geweldige inspiratie zijn voor nieuwkomers!
Ik gebruik Ubuntu 16.014 LTS x64. Python 3.5.2 (standaard, 17 november 2016, 17:05:23)
[GCC 5.4.0 20160609] op linux