Bonne façon dynamique d'importer un module avec une relative des importations?
J'ai besoin dynamiquement des modules d'importation dans mon projet d'un autre paquet.
La structure est comme:
project_folder/
project/
__init__.py
__main__.py
plugins/
__init__.py
plugin1/
__init__.py
...
plugin2/
__init__.py
...
J'ai fait cette fonction pour charger un module:
import os
from importlib.util import spec_from_file_location, module_from_spec
def load_module(path, name=""):
""" loads a module by path """
try:
name = name if name != "" else path.split(os.sep)[-1] # take the module name by default
spec = spec_from_file_location(name, os.path.join(path, "__init__.py"))
plugin_module = module_from_spec(spec)
spec.loader.exec_module(plugin_module)
return plugin_module
except Exception as e:
print("failed to load module", path, "-->", e)
Il fonctionne, à moins que le module utilise relative des importations:
failed to load module /chemin/vers/plugins/plugin1 --> Parent module "plugin1' a pas été chargé, ne peut pas effectuer relative à l'importation
Ce que je fais mal?
- La solution est donnée dans le cette réponse: vous devez également ajouter le module importé à
sys.modules
de sorte que la relative à l'importation des œuvres. I. e. incluresys.modules[spec.name] = plugin_module
juste avant l'appel àspec.loader.exec_module(plugin_module)
.
Vous devez vous connecter pour publier un commentaire.
J'ai réussi à résoudre mon problème après BEAUCOUP de recherche sur google. S'avère que j'ai besoin d'importer à l'aide de chemins d'accès relatifs:
from plugins.config import *
, à l'aide de import_module ou _import_ ?J'ai eu un problème similaire il n'ya pas longtemps. J'ai ajouté le chemin d'accès du dossier du projet à l'sys.chemin d'accès en utilisant le module de chemin absolu comme ceci:
Cela s'ajoute la project_folder pour le sys.chemin permettant ainsi à l'instruction import pour trouver le plugin modules.
project/__main__.py
fichier avant que j'appelleload_module
. Est-ce la bonne place pour le mettre?__init__.py
fichier dans le project_folder.Comment nous pouvons le voir dans la doc officielle de importlib:
Pourquoi ne pas l'essayer?