Динамическая загрузка модулей Python

Одной из стратегий, которой я хотел бы следовать, является создание класса Handle для каждого объекта модели данных. Поскольку дескриптор отвечает только за изменение этого объекта данных, он следует SRP. Если мне нужно создать классы вне модификации объекта данных, по крайней мере, я знаю, что большая часть кода уже соответствует SRP.

50
задан 4 revs, 4 users 65%No Name 25 July 2019 в 22:07
поделиться

5 ответов

Ваш код почти правильный.

См. __ import __ function.

def doSomething(name):
    name = "package." + name
    mod = __import__(name, fromlist=[''])
    mod.doSomething()
55
ответ дан 7 November 2019 в 10:49
поделиться

Один трюк с ответом Бастьена ... Функция __ import __ () возвращает объект пакета, а не объект модуля. Если вы используете следующую функцию, она динамически загрузит модуль из пакета и вернет вам модуль, а не пакет.

def my_import(name):
    mod = __import__(name)
    components = name.split('.')
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

Затем вы можете сделать:

mod = my_import('package.' + name)
mod.doSomething()
9
ответ дан 7 November 2019 в 10:49
поделиться

Бастьен уже ответил на этот вопрос, в любом случае вы можете найти полезную эту функцию, которую я использую для загрузки всех модулей из подпапки в словаре:

def loadModules():
    res = {}
    import os
    # check subfolders
    lst = os.listdir("services")
    dir = []
    for d in lst:
        s = os.path.abspath("services") + os.sep + d
        if os.path.isdir(s) and os.path.exists(s + os.sep + "__init__.py"):
            dir.append(d)
    # load the modules
    for d in dir:
        res[d] = __import__("services." + d, fromlist = ["*"])
    return res

Эта другая функция предназначена для создания экземпляра объекта с помощью класс, определенный в одном из модулей, загруженных первой функцией:

def getClassByName(module, className):
    if not module:
        if className.startswith("services."):
            className = className.split("services.")[1]
        l = className.split(".")
        m = __services__[l[0]]
        return getClassByName(m, ".".join(l[1:]))
    elif "." in className:
        l = className.split(".")
        m = getattr(module, l[0])
        return getClassByName(m, ".".join(l[1:]))
    else:
        return getattr(module, className)

Простой способ использования этих функций:

mods = loadModules()
cls = getClassByName(mods["MyModule"], "submodule.filepy.Class")
obj = cls()

Очевидно, вы можете заменить все ссылки на подпапку "services" параметрами.

23
ответ дан 7 November 2019 в 10:49
поделиться

Добавьте каталог модуля в sys.path и используйте обычный оператор import .

-1
ответ дан 7 November 2019 в 10:49
поделиться

Для обнаружения изменений в каталоге в Linux вы можете использовать pyinotify ( здесь - хороший рабочий пример); на Mac - fsevents (через пакет PyObjC, поставляемый с вашим Mac); в Windows: Уведомления об изменении каталога через win32api (или модуль стандартной библиотеки Python ctypes ). AFAIK, никто не объединил эти различные подходы в один портативный пакет. (Конечно, в худшем случае вы можете вернуться к «более низким технологиям», таким как периодические опросы, как статья Тима Голдена , возможно, с легким «предупреждением от внешнего процесса» через сигнал и т. Д. ).

Как только вы получите уведомление и имя нового или измененного модуля,

3
ответ дан 7 November 2019 в 10:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: