2010-11-07 11 views
19

J'ai un module Python que je veux importer dynamiquement avec seulement une chaîne du nom du module. Normalement j'utilise importlib ou __import__ et cela fonctionne assez bien étant donné que je sais quels objets je veux importer depuis le module, mais est-il possible de faire l'équivalent de import * dynamiquement. Ou y a-t-il une meilleure approche?Importer tout dynamiquement (*) à partir d'un module

Je sais en général qu'il est mauvais d'utiliser import * mais les modules que j'essaie d'importer sont générés automatiquement à la volée et je n'ai aucun moyen de connaître le module exact qui contient la classe que j'adresse.

Merci.

+0

Ainsi, alors qu'il ya des façons de faire ce travail, comme @GWW la liste - il ne serait pas une bonne chose à faire. Vous devriez vraiment considérer attribuer un nom au module importé avec __import__, et utiliser "getattr" et même la syntaxe point pour accéder à ses membres. – jsbueno

Répondre

5

Je suis venu avec un code hacky moche, ça marche en python 2.6. Je ne sais pas si cela est la chose la plus intelligente à faire bien, peut-être d'autres personnes ici ont une idée:

test = __import__('os',globals(),locals()) 
for k in dir(test): 
    globals()[k] = test.__dict__[k] 

Vous voulez probablement mettre un chèque ici pour vous assurer que vous n'écrasez pas quoi que ce soit dans la espace de noms global. Vous pourriez probablement éviter la partie globals et simplement regarder à travers chaque module importé dynamiquement pour votre classe d'intérêt. Ce serait probablement mieux que de polluer l'espace de noms global avec tout ce que vous importez.

Par exemple, supposons que votre classe est nommée Demande de urllib2

test = __import__('urllib2',globals(),locals()) 
cls = None 
if 'Request' in dir(test): 
    cls = test.__dict__['Request'] 
    # you found the class now you can use it! 
    cls('http://test.com') 
+0

Ce que je vous suggère de faire est de rechercher le contenu de chacun de ces modules "générés" pour le nom de la classe d'intérêt. Je suppose que vous connaissez au moins le nom de la classe que vous recherchez. J'ai édité ma réponse pour vous donner un exemple. – GWW

+2

En fait, c'est moins hackish que yoyu peut penser - il a exactement le même effet que "from import *" - comme ce que cette déclaration fait est de mettre à jour le dictionnaire global actuel. C'est le même dictionnaire récupéré par un appel aux globals(). En ce qui concerne les "vérifications", vous avertissez l'OP de: notez que "import *" lui-même écrase tout simplement :-) – jsbueno

+0

Je suppose que ce n'est pas si mal alors. Je pense que j'ai toujours l'impression qu'il y a une façon «plus élégante» de faire des choses en python. – GWW

0

La seule façon de le faire est d'utiliser exec() et de générer dynamiquement la commande importlib à la volée.

+1

Comme vous pouvez le voir, il existe de meilleurs moyens. – jsbueno

+2

Oui, je peux maintenant voir :) – g19fanatic

20

Utilisez update pour dicts:

globals().update(importlib.import_module('some.package').__dict__) 

Notez que l'utilisation a_module.__dict__ n'est pas la même chose que from a_module import *, parce que tous les noms sont "importé", non seulement ceux de __all__ ou ne commençant pas par _.

+4

C'est légèrement mieux que la réponse de GWW, car il utilise la mise à jour au lieu d'une itération sur le module. –

2

Ce qui suit est très péché et vous condamnera au Purgatoire ou pire

# module A 
myvar = "hello" 

# module B 
import inspect 
def dyn_import_all(modpath): 
    """Incredibly hackish way to load into caller's global namespace""" 
    exec('from ' + modpath + ' import *', inspect.stack()[1][0].f_globals) 

# module C 
from module B import dyn_import_all 
def print_from(modpath): 
    dyn_import_all(modpath) 
    print(myvar) 
+1

vous avez oublié 'os.system ('rm -rf ....' à la fin là .. – gauteh

Questions connexes