Question

Il semble qu'ils aient annulé dans Python 3 tout le moyen facile de charger rapidement un script en supprimant execfile ()

Existe-t-il une alternative évidente qui me manque?

Était-ce utile?

La solution

Selon la documentation , au lieu de

execfile("./filename") 

Utiliser

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

Voir:

Autres conseils

Vous êtes simplement censé lire le fichier et exécuter le code vous-même. 2to3 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 de fichier à l'objet de code, ce qui facilite le débogage.)

Voir:

Alors que exec (open ("nom de fichier"). read ()) est souvent donné comme alternative à execfile ("nom de fichier") , il manque beaucoup les détails que execfile est pris en charge.

La fonction suivante pour Python3.x est aussi proche que possible d’avoir le même comportement que l’exécution directe d’un fichier. Cela correspond à l'exécution de 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")

Remarques:

  • Utilise la lecture binaire pour éviter les problèmes d'encodage
  • Garanti de fermer le fichier (Python3.x en avertit)
  • Définit __ main __ , certains scripts en dépendent pour vérifier s’ils se chargent en tant que module ou non, par exemple. if __name__ == " __ main __ "
  • La définition de __ fichier __ est préférable pour les messages d'exception et certains scripts utilisent __ fichier __ pour obtenir les chemins des autres fichiers les concernant.
  • Prend globals en option & amp; locals, en les modifiant sur place comme le fait execfile - pour que vous puissiez accéder à toutes les variables définies en les relisant après leur exécution.

  • Contrairement à execfile de Python2, ne ne modifie pas l'espace de nom actuel par défaut. Pour cela, vous devez explicitement indiquer globals () & amp; locals () .

Comme suggéré sur la liste de diffusion python-dev Récemment, le module runpy pourrait constituer 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 existe des différences subtiles avec execfile :

  • run_path crée toujours un nouvel espace de noms. Il exécute le code en tant que module, il n'y a donc pas de différence entre globals et locaux (c'est pourquoi il n'y a qu'un argument init_globals ). Les globals sont renvoyés.

    execfile exécuté dans l'espace de noms actuel ou dans l'espace de noms donné. La sémantique de locals et de globals , si elle est donnée, était similaire aux locals et aux globals d'une définition de classe.

  • run_path peut non seulement exécuter des fichiers, mais également des oeufs et des répertoires (reportez-vous à sa documentation pour plus de détails).

Celui-ci est meilleur, car il prend les globaux 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)

Vous pouvez écrire votre propre fonction:

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

Si vous aviez vraiment besoin de ...

Si le script que vous souhaitez charger se trouve dans le même répertoire que celui que vous exécutez, vous pouvez peut-être utiliser l'option "import". va faire le travail?

Si vous devez importer dynamiquement du code, la fonction intégrée __ import __ et le module imp méritent d'être examinés.

>>> 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 une version ultérieure, vous devriez également consulter importlib .

Voici ce que j'avais (le fichier est déjà affecté au chemin du fichier contenant le code source dans les deux exemples):

execfile(file)

Voici ce que j'ai remplacé par:

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

Ma partie préférée: la deuxième version fonctionne très bien en Python 2 et 3, ce qui signifie qu'il n'est pas nécessaire d'ajouter une logique dépendante de la version.

Notez que le modèle ci-dessus échouera si vous utilisez des déclarations de codage PEP-263. qui ne sont pas ascii ou utf-8. Vous devez trouver le codage des données et le coder correctement avant de le donner à 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)

De même, bien que vous n'utilisiez pas IPython (comme vous devriez probablement le faire), vous pouvez le faire:

%run /path/to/filename.py

Ce qui est tout aussi facile.

Je suis juste un débutant ici, alors peut-être que c'est de la pure chance si j'ai trouvé ceci:

Après avoir tenté d'exécuter un script à partir de l'invite de l'interprète, > > > avec la commande

    execfile('filename.py')

pour lequel j'ai reçu un " NameError: le nom 'execfile' n'est pas défini & "; J'ai essayé un très basique

    import filename

cela a bien fonctionné: -)

J'espère que cela peut être utile et je vous remercie pour vos astuces, vos exemples et tous ces bouts de code commentés qui sont une excellente source d'inspiration pour les nouveaux arrivants!

J'utilise Ubuntu 16.014 LTS x64. Python 3.5.2 (défaut, le 17 novembre 2016, 17:05:23) [GCC 5.4.0 20160609] sur linux

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top