Qu'est-ce qu'une alternative à execfile en Python 3?
il semble qu'ils ont annulé en Python 3 tout le moyen facile de charger rapidement un script en supprimant execfile()
y a-t-il une alternative évidente que je ne vois pas?
12 réponses
selon la documentation , au lieu de
execfile("./filename")
Utiliser
exec(open("./filename").read())
voir:
Vous êtes seulement censés lire le fichier et exec le code vous-même. 2à3 actuel remplace
execfile("somefile.py", global_vars, local_vars)
comme
with open("somefile.py") as f:
code = compile(f.read(), "somefile.py", 'exec')
exec(code, global_vars, local_vars)
(l'appel de compilation n'est pas strictement nécessaire, mais il associe le nom du fichier à l'objet code, ce qui rend le débogage un peu plus facile.)
voir:
comme suggéré sur la liste de diffusion python-dev récemment, le module runpy pourrait être une alternative viable. Citant ce message:
https://docs.python.org/3/library/runpy.html#runpy.run_path
import runpy file_globals = runpy.run_path("file.py")
il y a des différences subtiles à execfile
:
-
run_path
crée toujours un nouvel espace de noms. Il exécute le code comme un module, donc il n'y a pas de différence entre les globals et les locals (c'est pourquoi il n'y a qu'un argumentinit_globals
). Les variables globales sont retournés.execfile
exécuté dans l'espace de noms courant ou de l'espace de noms donné. La sémantique delocals
etglobals
, si elle est donnée, est similaire à celle des locaux et des globals à l'intérieur d'une définition de classe. -
run_path
peut non seulement exécuter des fichiers, mais aussi des eggs et des répertoires (voir sa documentation pour plus de détails).
alors que exec(open("filename").read())
est souvent donné comme une alternative à execfile("filename")
, il manque pas mal de détails que execfile
pris en charge.
la fonction suivante pour Python3.x est aussi proche que j'ai pu obtenir pour avoir le même comportement que l'exécution d'un fichier directement. Ça correspond à 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")
Notes:
- utilise la lecture binaire pour éviter l'encodage les questions de
- garanti pour fermer le fichier (Python3.x avertit à ce sujet)
- définit
__main__
.if __name__ == "__main__"
- définir
__file__
est plus agréable pour les messages d'exception et certains scripts utilisent__file__
pour obtenir les chemins d'autres fichiers relatifs à eux. -
prend facultatif les arguments globals & locals, en les modifiant en place comme
execfile
le fait-de sorte que vous pouvez accéder à toutes les variables définies en relisant les variables après exécution. -
contrairement à
execfile
de Python2, ne modifie pas l'espace de noms actuel par défaut. Pour cela, vous devez explicitement passer dansglobals()
.
vous pourriez écrire votre propre fonction:
def xfile(afile, globalz=None, localz=None):
with open(afile, "r") as fh:
exec(fh.read(), globalz, localz)
si vous en aviez vraiment besoin...
celui-ci est mieux, car il prend les globals et les locaux de l'appelant:
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)
Si le script que vous voulez charger dans le même répertoire que celui que vous exécutez, peut-être "importer" va faire le travail ?
si vous avez besoin d'importer dynamiquement le code de la fonction intégrée _ _ import__ et le module imp sont à regarder.
>>> 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!"
si vous utilisez Python 3.1 ou plus tard, vous devriez aussi jeter un oeil à importlib .
voici ce que j'avais ( file
est déjà assigné au chemin du fichier avec le code source dans les deux exemples):
execfile(file)
voici ce que je l'ai remplacé par:
exec(compile(open(file).read(), file, 'exec'))
ma partie préférée: la seconde version fonctionne très bien en Python 2 et 3, ce qui signifie qu'il n'est pas nécessaire d'ajouter la logique dépendante de la version.
notez que le modèle ci-dessus échouera si vous utilisez des déclarations d'encodage PEP-263 ce ne sont pas des ascii ou des utf-8. Vous devez trouver le codage des données, et l'encoder correctement avant de le remettre à 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)
aussi, bien que ce ne soit pas une solution Python pure, si vous utilisez IPython( comme vous le devriez probablement de toute façon), vous pouvez le faire:
%run /path/to/filename.py
ce qui est tout aussi facile.
je suis juste un internaute novice ici donc peut-être que c'est de la pure chance si je trouve ceci:
Après avoir essayé d'exécuter un script à partir de l'interprète invite >>> avec la commande
execfile('filename.py')
pour lequel j'ai obtenu un "NameError: nom' execfile 'n'est pas défini" j'ai essayé un très basique
import filename
il a bien fonctionné :-)
j'espère que cela peut être utile et je vous remercie tous pour les grands conseils, les exemples et toutes ces magistrales commenté morceaux de code qui sont une grande source d'inspiration pour les nouveaux arrivants !
J'utilise Ubuntu 16.014 LTS x64. Python 3.5.2 (par défaut, le 17 Novembre 2016, 17:05:23) [GCC 5.4.0 20160609] sur linux
localisez la route de votre installation de dossier (je l'ai en C:\python34) puis exécutez sur un shell cmd régulier
set path=%path%;c:\python34
maintenant quand vous initiez un shell, passez à C:\python34\myscripts et utilisez la commande classique
python filename.py