Comment puis-je importer un fichier source arbitraire python (dont le nom de fichier peut contenir des caractères et ne se termine pas toujours par .py
) Dans Python 3,3 + ?
J'ai utilisé imp.load_module
comme suit:
>>> import imp
>>> path = '/tmp/a-b.txt'
>>> with open(path, 'U') as f:
... mod = imp.load_module('a_b', f, path, ('.py', 'U', imp.PY_SOURCE))
...
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Il fonctionne toujours en Python 3.3, mais selon la documentation de imp.load_module
, Il est déconseillé:
Déconseillé depuis la version 3.3: Inutile car les chargeurs doivent être utilisés pour charger les modules et find_module () est déconseillé.
et la documentation du module imp
recommande d'utiliser importlib
:
Remarque Les nouveaux programmes devraient utiliser importlib plutôt que ce module.
Quelle est la bonne façon de charger un fichier source arbitraire python dans Python 3.3+ sans utiliser la fonction imp.load_module
Déconseillée)?
Trouvé une solution à partir de importlib
code de test .
Utilisation de importlib.machinery.SourceFileLoader :
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = loader.load_module()
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
[~ # ~] note [~ # ~] : ne fonctionne que dans Python 3.3 +.
[~ # ~] mise à jour [~ # ~] Loader.load_module
est déconseillé depuis Python 3.4. Utilisez Loader.exec_module
à la place:
>>> import types
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = types.ModuleType(loader.name)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b'>
>>> import importlib.machinery
>>> import importlib.util
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> spec = importlib.util.spec_from_loader(loader.name, loader)
>>> mod = importlib.util.module_from_spec(spec)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Version plus courte de la solution de @falsetru:
>>> import importlib.util
>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')
>>> mod = importlib.util.module_from_spec(spec)
>>> spec.loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Je l'ai testé avec Python 3.5 et 3.6.
Selon les commentaires, cela ne fonctionne pas avec des extensions de fichiers arbitraires.
Similaire à @falsetru mais pour Python 3.5 + et en tenant compte de ce que le importlib
doc indique sur l'utilisation de importlib.util.module_from_spec
plus de types.ModuleType
:
Cette fonction [
importlib.util.module_from_spec
] est préférable à l'utilisation detypes.ModuleType
pour créer un nouveau module selon les spécifications est utilisé pour définir autant d'attributs contrôlés par l'importation sur le module que possible.
Nous pouvons importer n'importe quel fichier avec importlib
seul en modifiant le importlib.machinery.SOURCE_SUFFIXES
liste.
import importlib
importlib.machinery.SOURCE_SUFFIXES.append('') # empty string to allow any file
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# if desired: importlib.machinery.SOURCE_SUFFIXES.pop()