Динамическая загрузка модулей Python
Вопрос
Я пытаюсь динамически загружать созданные мной модули.
Сейчас это работает правильно:
import structures.index
Но если я попробую то же самое, импортировав его динамически, это не удастся.
struct = __import__("structures.index")
Предоставленная ошибка:
Error ('No module named structures.index',)
Есть идеи, почему?
Редактировать:При использовании полной области (это вроде работает?):
struct = __import__("neoform.structures.index")
Это не вызывает никаких ошибок, однако не загружает индексный модуль, а вместо этого загружает модуль «neoform».
Результат «struct»:
<module 'neoform' from '/neoform/__init__.py'>
Кроме того, в качестве побочного вопроса: как мне затем создать экземпляр класса внутри динамически загружаемого модуля?(при условии, что все модули содержат общее имя класса).
Редактировать:Решение:(спасибо coonj и Рику) В итоге это сработало.Не знаю почему (пока), но fromlist
очевидно, должно было быть что-то «что угодно», поскольку это сработало, когда я поставил букву «а» в качестве значения (странно, учитывая, что в файле был только 1 класс).
def get_struct_module(self, name):
try:
return = __import__("neoform.structures." + name, fromlist='*')
except ImportError, e:
self.out.add("Could not load struct: neoform.structure." + name + "\n\n" + "Error " + str(e.args))
Решение
Я не уверен, что означает «это не удалось», поэтому просто упомяну об этом. __import__('structures.index')
на самом деле должно работать, но оно не присваивает имя модуля в текущей области.Чтобы сделать это (а затем использовать класс в динамически импортируемом модуле), вам придется использовать:
structures = __import__('structures.index')
structures.index.SomeClass(...)
Полная информация о __import__
доступны здесь.
Редактировать:(на основе редактирования вопроса)
Импортировать neoform.structures.index
, и верните index
модуль, вы должны сделать следующее:
structures = __import__('neoform.structures.index',
fromlist=['does not in fact matter what goes here!'])
Итак, если у вас есть список имен пакетов packages
, вы можете импортировать их index
модули и создать экземпляры некоторых MyClass
класс для каждого, используя следующий код:
modules = [ __import__('neoform.%s.index' % pkg, fromlist=['a'])
for pkg in packages ]
objects = [ m.MyClass() for m in modules ]
Другие советы
Чтобы импортировать подмодули, вам необходимо указать их в поле fromlist
аргумент __import__()
Например, эквивалент:
import structures.index
является:
structures = __import__('structures', fromlist=['index'])
Сделать это на карте немного сложнее...
import mod1.index
import mod2.index
import mod3.index
Для этого импорта вам нужно определить новую функцию, чтобы получить index
субмодуль из каждого модуля:
def getIndexMods(mod_names):
mod_list = map(lambda x: __import__(x, fromlist='index'))
index_mods = [mod.index for mod in mod_list]
return index_mods
Теперь вы можете сделать это, чтобы получить ссылки на все индексные модули:
index_mods = getIndexMods(['mod1', 'mod2', 'mod3'])
Кроме того, если вы хотите получить подмодули, которые не называются «индекс», вы можете сделать это:
mod1, mod2, mod3 = map(lambda x,y: __import__(x, fromlist=y),
['mod1', 'mod2', 'mod3'], ['index1', 'index2', 'index3'])
Используйте полную область действия («neoform.structures.index») с этим вспомогательным методом.
def import_module(name):
mod = __import__(name)
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
module = import_module("neoform.structures.index")
# do stuff with module
Java-программист здесь, но я думаю, вам нужен модуль имп
>>> import imp
>>> fm = imp.find_module('index', ['./structures']) # for submodule
>>> mymod = imp.load_module('structures.index', *fm)
>>> mymod
<module 'structures.index' from './structures/index.pyc'>
>>> x = mymod.insideIndex()
Initialising index class...
Вуаля!
С какой стати тебе заменить
import structures.index
с
map(__import__, ["structures.index"])
Первый (а) работает, (б) является динамический и (c) поддерживается напрямую.Какой возможный вариант использования существует для замены легко изменяемого исходного текста в виде простого текста чем-то более сложным?
Суммируя:не делай этого.Это не имеет никакой ценности.
Редактировать
«Я получаю импорт из базы данных» — это благородное усилие, но все же неразумное.Какой блок кода зависит от этого импорта?Весь этот блок кода — импорт и все такое — это то, что вы хотите выполнить.Весь этот блок кода — импорт, инструкции и все остальное — должен быть обычным старым файлом модуля Python.
Импортируйте этот блок кода из файловой системы.Используйте базу данных, чтобы определить, какой файл, автора файла — все, для чего вы хотите использовать базу данных.Но просто импортируйте и запустите модуль самым простым способом.
Действительно поздно постить здесь.Но я искал этот вопрос в Google.Я сделал несколько проб и ошибок.Не уверен, что этот фрагмент поможет, но вот он.Использование его для сайта Flask.
modules = ['frontend', 'admin']
for module in modules:
mod = __init__('controllers.%s' % module, fromlist=[module])
app.register_blueprint(mod.blueprint_mod)
# or
from importlib import import_module
modules = ['frontend', 'admin']
for module in modules:
mod = import_module('controllers.%s' % module)
app.regitster_blueprint(mod.blueprint_mod)