Как найти все дочерние модули в Python? - PullRequest
13 голосов
/ 26 мая 2009

Хотя в Python довольно просто импортировать «дочерний» модуль в другой модуль и перечислить его атрибуты, становится немного сложнее импортировать все дочерние модули.

Я создаю библиотеку инструментов для существующего 3D-приложения. Каждый инструмент имеет свой собственный пункт меню и подменю. Мне бы хотелось, чтобы инструмент отвечал за создание собственных меню, так как многие из них меняются в зависимости от контекста и шаблонов. Я бы хотел, чтобы мой базовый модуль мог найти все дочерние модули, проверить функцию create_menu() и вызвать ее, если найдет.

Какой самый простой способ обнаружить все дочерние модули?

Ответы [ 5 ]

3 голосов
/ 06 сентября 2011

Я думаю, что лучший способ сделать плагин такого типа - использовать entry_points и API для их запроса .

1 голос
/ 07 сентября 2011

Решение, приведенное выше для обхода файловой системы для поиска подмодулей, приемлемо, если вы реализуете каждый плагин как модуль на основе файловой системы.

Более гибкий способ - это явный список плагинов в вашем главном модуле, и каждый плагин (будь то модуль, созданный файлом, динамически или даже экземпляром класса) явно добавляет себя в этот список. Может быть, через функцию registerPlugin.

Помните: «явное лучше, чем неявное» является частью дзен Python.

1 голос
/ 26 мая 2009

Когда я был добрым и только начинал программировать на Python, я написал это для моего модульного бота IRC:


    # Load plugins

    _plugins = []

    def ifName(name):
        try:
            return re.match('([^_.].+)\.[^.]+', a).group(1)
        except:
            return None

    def isValidPlugin(obj):
        from common.base import PluginBase
        try:
            if obj.__base__ == PluginBase:
                return True
            else:
                return False
        except:
            return False

    plugin_names = set(ifilter(lambda a: a!=None, [ifName(a) for a in os.listdir(os.path.join(os.getcwd(), 'plugins'))]))
    for plugin_name in plugin_names:
        try:
            plugin = __import__('plugins.'+plugin_name, fromlist=['plugins'])
            valid_plugins = filter(lambda a: isValidPlugin(a), [plugin.__getattribute__(a) for a in dir(plugin)])
            _plugins.extend(valid_plugins)
        except Exception, e:
            logger.exception('Error loading plugin %s', plugin_name)

    # Run plugins

    _plugins = [klass() for klass in _plugins]

Это небезопасный или "правильный" способ, но, может быть, мы все же будем полезны. Это очень старый код, поэтому, пожалуйста, не бейте меня.

0 голосов
/ 26 мая 2009

Вы можете попробовать glob bing в каталоге:

import os
import glob

modules = glob.glob(os.path.join('/some/path/to/modules', '*.py'))

Тогда вы можете попробовать импортировать их:

checked_modules
for module in modules:
    try:
        __import__(module, globals(), locals()) # returns module object
    except ImportError:
        pass
    else:
        checked_modules.append(module)
0 голосов
/ 26 мая 2009

с использованием dir () и модуль imp

...