Lorsque vous utilisez __import__
avec un nom en pointillé, comme par exemple: somepackage.somemodule
, le module renvoyé n'est pas somemodule
, tout ce qui est renvoyé semble être en grande partie vide! que se passe t-il ici?
Réponses
Trop de publicités?À partir du python docs sur __import__
:
__import__( name[, globals[, locals[, fromlist[, level]]]])
...
Lorsque le nom de la variable est de la forme package.module, normalement, l' package de niveau supérieur (le nom jusqu'à le premier point) est retournée, et non pas le module nommé par son nom. Toutefois, lorsqu'un non-vide fromlist argument est donné, le module appelé par son nom est retourné. Ceci est fait pour assurer la compatibilité avec le bytecode généré pour l' différents types d'instruction d'importation; lors de l'utilisation de "l'importation de spam.le jambon.les œufs", le package de niveau supérieur spam doit être placé dans l espace de noms, mais quand à l'aide de "contre le spam.jambon importer des œufs", le le spam.ham sous-paquetage doit être utilisé pour trouver les œufs variable. En tant que solution de contournement pour ce problème, utilisez l' getattr() pour extraire les des composants. Par exemple, vous pourriez définir l'assistance suivante:
def my_import(name): mod = __import__(name) components = name.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod
Pour paraphraser:
Lorsque vous demandez somepackage.somemodule
, __import__
retours somepackage.__init__.py
, ce qui est souvent vide.
Il sera de retour somemodule
si vous fournissez fromlist
(une liste des noms de variable à l'intérieur d' somemodule
vous voulez, qui ne sont en fait pas retourné)
Vous pouvez aussi, comme je l'ai fait, l'utilisation de la fonction qu'ils suggèrent.
Note: j'ai posé cette question avec l'intention de répondre moi-même. Il y a un gros bug dans mon code, et d'avoir mal diagnostiquée, il m'a fallu du temps pour le comprendre, alors j'ai pensé aider à la soi une communauté et après la chasse aux sorcières que j'ai rencontré ici.
Il existe une solution plus simple, comme expliqué dans la documentation:
Si vous souhaitez simplement importer un module (éventuellement dans un package) par son nom, vous pouvez appeler __import __ () puis le rechercher dans sys.modules:
>>> import sys
>>> name = 'foo.bar.baz'
>>> __import__(name)
<module 'foo' from ...>
>>> baz = sys.modules[name]
>>> baz
<module 'foo.bar.baz' from ...>
Il y a quelque chose qui fonctionne comme vous le souhaitez: twisted.python.reflect.namedAny
:
>>> from twisted.python.reflect import namedAny
>>> namedAny("operator.eq")
<built-in function eq>
>>> namedAny("pysqlite2.dbapi2.connect")
<built-in function connect>
>>> namedAny("os")
<module 'os' from '/usr/lib/python2.5/os.pyc'>
Pour Python 2.6, j'ai écrit cet extrait:
def import_and_get_mod(str, parent_mod=None):
"""Attempts to import the supplied string as a module.
Returns the module that was imported."""
mods = str.split('.')
child_mod_str = '.'.join(mods[1:])
if parent_mod is None:
if len(mods) > 1:
#First time this function is called; import the module
#__import__() will only return the top level module
return import_and_get_mod(child_mod_str, __import__(str))
else:
return __import__(str)
else:
mod = getattr(parent_mod, mods[0])
if len(mods) > 1:
#We're not yet at the intended module; drill down
return import_and_get_mod(child_mod_str, mod)
else:
return mod