Как сделать эквивалент "import * from module" с функцией Python __import__?
Учитывая строку с именем модуля, как вы импортируете все в модуле, как если бы вы вызывали:
from module import *
то есть. заданной строкой S = "модуль", как получить эквивалент следующего:
__import__(S, fromlist="*")
Это не похоже на выполнение, как ожидалось (поскольку оно ничего не импортирует).
Ответы
Ответ 1
Пожалуйста, передумайте. Единственное, что хуже, чем import *
, - магия import *
.
Если вы действительно хотите:
m = __import__ (S)
try:
attrlist = m.__all__
except AttributeError:
attrlist = dir (m)
for attr in attrlist:
globals()[attr] = getattr (m, attr)
Ответ 2
Здесь мое решение для динамического именования локальных файлов настроек для 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)
Ответ 3
Похоже, вы также можете использовать 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))
Ответ 4
Основная проблема заключается в том, что я разрабатываю 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())
Что отлично подходит для наших целей.
Ответ 5
Я не нашел хорошего способа сделать это, поэтому я взял более простой, но уродливый путь от 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