Chargement dynamique des modules Python
Question
Je suis en train de charger dynamiquement des modules que j'ai créés.
En ce moment, ce fonctionne correctement:
import structures.index
Mais si je tente la même chose en importer dynamiquement, il échoue.
struct = __import__("structures.index")
Erreur fourni est la suivante:
Error ('No module named structures.index',)
Toutes les idées pourquoi?
Edit: Lorsque vous utilisez la portée complète (il sorte de travaux?):
struct = __import__("neoform.structures.index")
Cela ne jette pas des erreurs, cependant, il ne se charge pas le module d'index, il est le chargement du module « neoform » à la place.
Le résultat de "struct" est:
<module 'neoform' from '/neoform/__init__.py'>
En outre, comme une question de côté, comment puis-je instancier puis une classe dans un module chargé dynamiquement? (En supposant que tous les modules contiennent un nom de classe commune).
Edit: Solution: (merci coonj et Rick) Cela a fini par être ce qui a fonctionné. Je ne sais pas pourquoi (encore), mais le fromlist
devait être quelque chose « quoi que ce soit en apparence, car il a travaillé quand je mets la lettre « a » comme valeur (étrange, étant donné que le fichier avait seulement 1 classe en elle).
def get_struct_module(self, name):
try:
return = __import__("neoform.structures." + name, fromlist='*')
except ImportError, e:
self.out.add("Could not load struct: neoform.structure." + name + "\n\n" + "Error " + str(e.args))
La solution
Je ne suis pas sûr de ce que « il ne » signifie, donc je vais juste mentionner que __import__('structures.index')
devrait, en fait, le travail, mais il ne lui assigne pas le nom du module dans le périmètre actuel. Pour ce faire (et utiliser une classe dans le module dynamique importé), vous devrez utiliser:
structures = __import__('structures.index')
structures.index.SomeClass(...)
Les détails sur __import__
sont disponibles .
Edit: (basé sur edit question)
Pour importer neoform.structures.index
et retourner le module index
, vous procédez comme suit:
structures = __import__('neoform.structures.index',
fromlist=['does not in fact matter what goes here!'])
Donc, si vous avez une liste de noms de paquets packages
, vous pouvez importer leurs modules index
et instancier une classe MyClass
pour chacun utilisant le code suivant:
modules = [ __import__('neoform.%s.index' % pkg, fromlist=['a'])
for pkg in packages ]
objects = [ m.MyClass() for m in modules ]
Autres conseils
Pour importer des sous-modules, vous devez les spécifier dans le arg fromlist
de __import__()
Fo exemple, l'équivalent de:
import structures.index
est:
structures = __import__('structures', fromlist=['index'])
Pour ce faire, dans une carte est un peu plus délicat ...
import mod1.index
import mod2.index
import mod3.index
Pour les importations, vous souhaitez définir une nouvelle fonction pour obtenir le sous-module index
de chaque module:
def getIndexMods(mod_names):
mod_list = map(lambda x: __import__(x, fromlist='index'))
index_mods = [mod.index for mod in mod_list]
return index_mods
Maintenant, vous pouvez le faire pour obtenir des références à tous les modules d'index:
index_mods = getIndexMods(['mod1', 'mod2', 'mod3'])
En outre, si vous voulez saisir des sous-modules qui ne sont pas nommés « index », vous pouvez alors faire ceci:
mod1, mod2, mod3 = map(lambda x,y: __import__(x, fromlist=y),
['mod1', 'mod2', 'mod3'], ['index1', 'index2', 'index3'])
Utiliser la portée complète (le "neoform.structures.index") avec cette méthode d'aide.
def import_module(name):
mod = __import__(name)
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
module = import_module("neoform.structures.index")
# do stuff with module
Java programmeur, mais je pense que vous avez besoin diablotin Module
>>> import imp
>>> fm = imp.find_module('index', ['./structures']) # for submodule
>>> mymod = imp.load_module('structures.index', *fm)
>>> mymod
<module 'structures.index' from './structures/index.pyc'>
>>> x = mymod.insideIndex()
Initialising index class...
Voila!
Pourquoi diable voulez-vous remplacer
import structures.index
avec
map(__import__, ["structures.index"])
La première (a) fonctionne, (b) dynamique et (c) est supporté directement. Quel cas possible l'utilisation est là pour remplacer facile à changer, source de texte brut avec quelque chose de plus complexe?
En bref: ne le faites pas. Il n'a pas de valeur.
Modifier
Le « Je reçois l'importation à partir d'une base de données » est un noble effort, mais pas encore sensible. Quel bloc de code dépend de ces importations? Ce bloc entier de code - importations et tout - est ce que vous voulez exécuter. Ce bloc entier de code - importations, déclarations et tout -. Doit être un fichier module python bon vieux
Importer ce bloc de code du système de fichiers. Utilisez la base de données pour identifier le fichier, l'auteur du fichier - tout ce que vous voulez utiliser la base de données. Mais simplement importer et d'exécuter le module le plus simple possible.
vraiment en retard post ici. Mais je cherchais cette question sur Google. Je l'ai fait quelques essais et erreurs. Je ne sais pas si cet extrait va aider, mais ici il est. Son utilisation pour le site Flask.
modules = ['frontend', 'admin']
for module in modules:
mod = __init__('controllers.%s' % module, fromlist=[module])
app.register_blueprint(mod.blueprint_mod)
# or
from importlib import import_module
modules = ['frontend', 'admin']
for module in modules:
mod = import_module('controllers.%s' % module)
app.regitster_blueprint(mod.blueprint_mod)