Динамическая загрузка модулей Python - PullRequest
3 голосов
/ 20 апреля 2009

Я пытаюсь динамически загружать созданные мной модули.

Сейчас это работает правильно:

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 & Rick) Это закончилось тем, что сработало. Не уверен, почему (пока), но fromlist должно было быть чем-то «что-то очевидным», поскольку оно работало, когда я помещал букву «a» в качестве значения (странно, учитывая, что в файле был только 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))

Ответы [ 7 ]

10 голосов
/ 20 апреля 2009

Я не уверен, что означает «оно терпит неудачу», поэтому я просто упомяну, что __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 ]
4 голосов
/ 20 апреля 2009

Чтобы импортировать подмодули, необходимо указать их в аргументе 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'])

Кроме того, если вы хотите получить субмодули, которые не называются «index», вы можете сделать это:

mod1, mod2, mod3 = map(lambda x,y: __import__(x, fromlist=y), 
  ['mod1', 'mod2', 'mod3'], ['index1', 'index2', 'index3'])
3 голосов
/ 21 апреля 2009

Использовать полный объем ("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
1 голос
/ 22 марта 2010
>>> 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...

Voila!

1 голос
/ 20 апреля 2009

Java программист здесь, но я думаю, вам нужен модуль imp

0 голосов
/ 15 марта 2013

Действительно поздно пост здесь. Но я искал этот вопрос в 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)
0 голосов
/ 20 апреля 2009

С какой стати вы бы заменили

import structures.index

с

map(__import__, ["structures.index"])

Первый (а) работает, (б) является динамическим и (с) поддерживается напрямую. Какой возможный вариант использования есть для замены простого изменяемого источника в виде простого текста чем-то более сложным?

Короче: не делай этого. Это не имеет никакого значения.


Редактировать

«Я получаю импорт из базы данных» - благородное усилие, но все же не имеет смысла. Какой блок кода зависит от этого импорта? Весь этот блок кода - импорт и все - это то, что вы хотите выполнить. Весь этот блок кода - импорт, операторы и все остальное - должен быть простым старым файлом модуля Python.

Импортировать этот блок кода из файловой системы. Используйте базу данных, чтобы определить, какой файл, автор файла - все, для чего вы хотите использовать базу данных. Но просто импортируйте и выполните модуль самым простым способом.

...