Come si fa a equivalere a "import * from module" con la funzione __import__ di Python?

StackOverflow https://stackoverflow.com/questions/147507

  •  02-07-2019
  •  | 
  •  

Domanda

Data una stringa con il nome di un modulo, come importare tutto nel modulo come se avessi chiamato:

from module import *

vale a dire. data stringa S = " module " ;, come si ottiene l'equivalente di quanto segue:

__import__(S, fromlist="*")

Questo sembra non funzionare come previsto (in quanto non importa nulla).

È stato utile?

Soluzione

Si prega di riconsiderare. L'unica cosa peggiore di import * è magic import * .

Se vuoi davvero:

m = __import__ (S)
try:
    attrlist = m.__all__
except AttributeError:
    attrlist = dir (m)
for attr in attrlist:
    globals()[attr] = getattr (m, attr)

Altri suggerimenti

Ecco la mia soluzione per la denominazione dinamica dei file delle impostazioni locali per Django. Nota l'aggiunta di seguito di un controllo per non includere gli attributi contenenti '__' dal file importato. Il __name__ globale veniva sovrascritto con il nome del modulo del file delle impostazioni locali, il che causava problemi con setup_environ () , usato in manage.py.

try:
    import socket
    HOSTNAME = socket.gethostname().replace('.','_')
    # See http://docs.python.org/library/functions.html#__import__
    m = __import__(name="settings_%s" % HOSTNAME, globals=globals(), locals=locals(), fromlist="*")
    try:
        attrlist = m.__all__
    except AttributeError:
        attrlist = dir(m)        
    for attr in [a for a in attrlist if '__' not in a]:
        globals()[attr] = getattr(m, attr)

except ImportError, e:
    sys.stderr.write('Unable to read settings_%s.py\n' % HOSTNAME)
    sys.exit(1)

Il problema di fondo è che sto sviluppando alcuni Django, ma su più di un host (con i colleghi), tutti con impostazioni diverse. Speravo di fare qualcosa del genere nel file project / settings.py:

from platform import node

settings_files = { 'BMH.lan': 'settings_bmh.py", ... } 

__import__( settings_files[ node() ] )

Sembrava una soluzione semplice (quindi elegante), ma sarei d'accordo sul fatto che abbia un odore e la semplicità esce dal ciclo quando devi usare la logica come ciò che John Millikin ha pubblicato (grazie). Ecco essenzialmente la soluzione con cui sono andato:

from platform import node

from settings_global import *

n = node()

if n == 'BMH.lan':
  from settings_bmh import *
# add your own, here...
else:
  raise Exception("No host settings for '%s'. See settings.py." % node())

Che funziona bene per i nostri scopi.

Sembra che tu possa anche usare dict.update () nei dizionari del modulo nel tuo caso:

config = [__import__(name) for name in names_list]

options = {}
for conf in config:
    options.update(conf.__dict__)

Aggiornamento: penso che ci sia un breve "funzionale" versione di esso:

options = reduce(dict.update, map(__import__, names_list))

Non ho trovato un buon modo per farlo, quindi ho preso un modo più semplice ma brutto da http://www.djangosnippets.org/snippets/600/

try:
    import socket
    hostname = socket.gethostname().replace('.','_')
    exec "from host_settings.%s import *" % hostname
except ImportError, e:
    raise e
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top