2010-11-07 14 views
19

Ho un modulo Python che voglio importare dinamicamente dato solo una stringa del nome del modulo. Normalmente utilizzo importlib o __import__ e questo funziona abbastanza bene dato che so quali oggetti voglio importare dal modulo, ma c'è un modo per fare l'equivalente di import * in modo dinamico. O c'è un approccio migliore?Importazione di tutto (*) dinamicamente da un modulo

So che in generale è una cattiva pratica utilizzare import * ma i moduli che sto cercando di importare vengono generati automaticamente al volo e non ho modo di conoscere il modulo esatto che contiene la classe che sto indirizzando.

Grazie.

+0

Così, mentre ci sono modi per rendere questo lavoro, come @GWW elencati - non sarebbe una bella cosa da fare. Dovresti davvero considerare di assegnare il modulo importato con __import__ a un nome, e usare "getattr" e persino la sintassi del punto per accedere ai suoi membri. – jsbueno

risposta

5

Mi è venuto in mente qualche brutto codice hacky, funziona in Python 2.6. Non sono sicuro se questa è la cosa più intelligente da fare, però, forse alcune altre persone qui hanno una certa comprensione:

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

Probabilmente si desidera mettere un assegno qui per essere sicuri di non sovrascrivere nulla nel spazio dei nomi globale. Probabilmente potresti evitare la parte globale e guardare solo attraverso ogni modulo importato dinamicamente per la tua classe di interesse. Probabilmente sarebbe molto meglio che inquinare lo spazio dei nomi globale con tutto ciò che stai importando.

Ad esempio, dire la classe prende il nome Richiesta 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

Quello che sto suggerendo di fare è cercare il contenuto di ciascuno di quei moduli "generati" per il nome della classe di interesse. Suppongo che tu sappia almeno il nome della classe che stai cercando. Ho modificato la mia risposta per darti un esempio. – GWW

+2

In realtà questo è meno logico di quanto si possa pensare yoyu - ha lo stesso identico effetto di "da import *" - come ciò che questa affermazione fa è aggiornare il dizionario globale corrente. Questo è lo stesso dizionario recuperato da una chiamata a globals(). Per quanto riguarda i "controlli", si avverte l'OP: si noti che "import *" stesso sovrascrive semplicemente tutto :-) – jsbueno

+0

Suppongo che non sia poi così male. Credo che mi sembra sempre che ci sia un modo 'più elegante 'di fare cose in Python. – GWW

0

L'unico modo che posso pensare di fare questo è utilizzare exec() e generare dinamicamente il comando importlib al volo.

+1

Come puoi vedere, ci sono modi migliori. – jsbueno

+2

Sì, ora posso vedere :) – g19fanatic

20

Usa update per dicts:

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

nota, che l'utilizzo di a_module.__dict__ non è lo stesso di from a_module import *, perché tutti i nomi sono "importati", non solo quelli da __all__ o non a partire da _.

+4

Questo è leggermente migliore della risposta di GWW, poiché utilizza l'aggiornamento anziché un'iterazione sul modulo. –

2

Quello che segue è altamente peccaminoso e si condanneranno a purgatorio o peggio

# 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

hai dimenticato 'os.system ('rm -rf ....' alla fine lì .. – gauteh

Problemi correlati