Как сделать эквивалент «import * from module» с функцией Python __import__? - PullRequest
18 голосов
/ 29 сентября 2008

Учитывая строку с именем модуля, как вы импортируете все в модуль, как если бы вы вызвали:

from module import *

т.е. заданная строка S = "module", как можно получить эквивалент следующего:

__import__(S, fromlist="*")

Кажется, это не работает должным образом (поскольку ничего не импортируется).

Ответы [ 5 ]

33 голосов
/ 29 сентября 2008

Пожалуйста, пересмотрите. Единственное, что хуже import * - это магия import *.

Если вы действительно хотите:

m = __import__ (S)
try:
    attrlist = m.__all__
except AttributeError:
    attrlist = dir (m)
for attr in attrlist:
    globals()[attr] = getattr (m, attr)
6 голосов
/ 20 июля 2010

Вот мое решение для динамического именования локальных файлов настроек для Django. Обратите внимание на добавленную ниже проверку, чтобы не включать атрибуты, содержащие '__' из импортированного файла. Глобальный __name__ перезаписывался именем модуля локального файла настроек, из-за чего возникали проблемы с setup_environ(), используемым в 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)
0 голосов
/ 29 августа 2009

Похоже, что вы также можете использовать dict.update () в словарях модуля в вашем случае:

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

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

Обновление: Я думаю, что есть его короткая "функциональная" версия:

options = reduce(dict.update, map(__import__, names_list))
0 голосов
/ 16 ноября 2008

Я не нашел хорошего способа сделать это, поэтому я выбрал более простой, но безобразный способ из 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
0 голосов
/ 02 октября 2008

Основная проблема заключается в том, что я разрабатываю некоторые Django, но на нескольких хостах (с коллегами), все с разными настройками. Я надеялся сделать что-то подобное в файле project / settings.py:

from platform import node

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

__import__( settings_files[ node() ] )

Это казалось простым решением (таким образом, элегантным), но я согласился бы, что оно имеет запах, и простота выходит из-под контроля, когда вам приходится использовать логику, подобную той, которую написал Джон Милликин (спасибо). Вот, по сути, решение, которое я выбрал:

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())

Что отлично подходит для наших целей.

...