Как организовать файловую структуру моей уже работающей системы плагинов? - PullRequest
5 голосов
/ 29 июля 2010

Я работаю над проектом, основным принципом которого является расширяемость.

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

class PieChart(ChartPluginAncestor):
    # Duck typing:
    # Implement compulsory methods for Plugins 
    # extending Chart functionality

и основная программа узнает о его присутствии, потому что PieChart будет включен в список зарегистрированных плагинов, доступных по адресу ChartPluginAncestor.plugins.

Будучи методом монтирования методом класса, все плагины регистрируются, когда их код класса загружается в память (то есть, даже до того, как объект этого класса будет создан) .

Система работает достаточно хорошо ™ для меня (хотя я всегда открыт для предложений о том, как улучшить архитектуру!), Но теперь мне интересно, как лучше всего управлять файлами плагинов ( т.е. где и как должны храниться файлы, содержащие плагины ).

Пока что я использую - для разработки - пакет, который я назвал "плагинами". Я помещаю все мои * .py файлы, содержащие классы плагинов, в каталог пакета, и я просто выдаю import plugins в файле main.py, чтобы все плагины были правильно смонтированы.

РЕДАКТИРОВАТЬ: Джефф указал в комментариях, что import plugins классы, содержащиеся в различных модулях пакетов, не будут легко доступны (я не понимал это, как я был - для целей отладки - импорт каждого класса отдельно с from plugins.myAI import AI).

Однако эта система хороша только во время разработки и тестирования кода, как:

  • Плагины могут поставляться с собственными юнит-тестами, и я не хочу загружать их в память.
  • Все плагины в настоящее время загружаются в память, но на самом деле есть некоторые плагины, которые являются альтернативными версиями одной и той же функции, поэтому вам просто нужно знать, что вы можете переключаться между ними, но вы хотите загрузить в память только тот, который вы выбрали на панели конфигурации.
  • В какой-то момент мне понадобится двойное расположение для установки плагинов: общесистемное расположение (например, где-то под /usr/local/bin/) и пользовательское (например, где-то под /home/<user>/.myprogram/).

Так что мои вопросы на самом деле - возможно, - три:

  1. Контейнер для плагинов: Какой самый разумный выбор для моей цели? отдельные файлы? пакеты? простой каталог файлов .py?)
  2. Распознавать наличие плагинов без необходимости их загрузки (импорта): Что такое умный способ использовать интроспекцию Python для этого?
  3. Размещение плагинов в двух разных местах: Существует ли стандартный / лучший способ (по крайней мере, для GNU / Linux) сделать это?

Ответы [ 2 ]

3 голосов
/ 29 июля 2010

Вопрос трудно решить, потому что потребности сложны.В любом случае, я попытаюсь с некоторыми предложениями.

О

Размещение плагинов в двух разных местах: есть ли стандартный способ / лучшие практики (по крайней мере, под GNU / Linux), чтобы сделатьчто?

Хороший подход - это virtualenv.Virtualenv - это модуль Python для сборки «изолированной» установки Python.Это лучший способ заставить отдельные проекты работать вместе.Вы получаете совершенно новый сайт-пакет, куда вы можете поместить свои плагины с соответствующими модулями проекта.

Попробуйте: http://pypi.python.org/pypi/virtualenv

Контейнер плагинов: что наиболееразумный выбор для моей цели?отдельные файлы?пакеты?простой каталог файлов .py?)

Хороший подход - это пакет python, который может выполнить «самостоятельную регистрацию» при импорте: просто определите внутри каталога пакета правильный init .py

Примером может быть http://www.qgis.org/wiki/Writing_Python_Plugins, а также API, описанный здесь http://twistedmatrix.com/documents/current/core/howto/plugin.html

См. также http://pypi.python.org/pypi/giblets/0.2.1

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

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

1 голос
/ 29 июля 2010

У меня также есть система плагинов с тремя типами плагинов, хотя я не утверждаю, что сделал это хорошо. Вы можете увидеть некоторые детали здесь .

Для внутренних плагинов у меня есть пакет (например, MethodPlugins), и в этом пакете есть модуль для каждого плагина (например, MethodPlugins.IRV). Вот как я загружаю плагины:

  1. Загрузить пакет (import MethodPlugins)

  2. Используйте pkgutil.iter_modules для загрузки всех модулей (например, MethodPlugins.IRV)

  3. Все плагины происходят от общего базового класса, поэтому я могу использовать __subclassess__ для их идентификации.

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

Для внешних плагинов у меня есть определенный каталог, в который пользователи могут поместить их, и я использую os.listdir для их импорта. Пользователь должен использовать правильный базовый класс, чтобы я мог их найти.

Мне было бы интересно улучшить и это, но оно также работает достаточно хорошо для меня. :)

...