Pull to refresh

Comments 45

Интересно, возьму на заметку.
Можно, наверное, оптимизировать. Каждый плагин при подключении регистрирует команды, которые он понимает, и тогда не нужно рассылать их всем.
+ за старание, но я бы поступил по другому. Можно создать некий менеджер плагинов. Когда плагин устанавливается от сообщает менеджеру всю информацию о себе, в том числе и какие команды понимает. Дальше приложение посылает команду менеджеру, который ищет необходимый плагин. Плагин эту информацию обрабатывает и возвращает ее менеджеру, который в свою очередь отдает ее приложению. Т.о. менеджер плагинов служит посредником между приложением и самими плагинами.
В реальном приложении вообще стоит делать отдельный «интерфейсный» класс, который будет содержать все методы воздействия плагина на приложение, и из плагина обращаться только к нему.
Собственно, статья только показывает, как связать __include__ & __subclasses__ для управления плагинами
+обдумать конфликты имен команд
Поддерживаю. Избрал этот же путь для нескольких приложений, включая генератор отчетов и модульный вики-рендерер. Неразумно заставлять программиста складывать весь код в один каталог, гораздо удобнее определять классы в произвольных местах и цеплять их к менеджеру, которым может быть и собственно родительский класс. Для автоматической регистрации классов можно использовать декораторы, метаклассы и т.д. по вкусу.
Как насчет использования стандартных абстрактных классов в плагинах? Необхождимости, конечно, нет, но позволяет жестко задать интерфейсную часть плагина.
Перенесите в «Язык программирования Python» :-)
Хорошо бы еще добавить в класс
def OnLoad(self):
опечатка…
def OnUnLoad(self):
Ну это описание метода, а интерфейс плагина каждый подгонит под свои нужды (:
Я к тому, что если предполагается какая-то инициализация плагина перед работой (например, подключение к БД), то хорошо бы предположить обратную операцию (например, закрытие подключения к БД).
Имхо, надуманный пример. Во-первых мне сложно представить такой юскейс, при котором плагины постоянно выгружались бы до завершения работы основного приложения. Во-вторых, большая часть вещей о который вы говорите, будь то соединения с БД случаться автоматически при попадании объектов в garbage collector. Ну а если хочется что-то специально чистить, то реализуйте __del__ в своем классе и всего делов,
Ну как сказать. Да, в питоне многие стандартные классы написаны так, что деструктор все делает за вас.
Поэтому когда вы выходите из программы, удаляете объект и пр. об этом думать не приходится. Но можно предположить случай, когда вам надо будет использовать нестандартный класс, который это все делать не будет.
Полагаю, что в нестандартном классе об этом и надо будет подумать, а не вводить лишние сущности сомнительного назначения.
И там тож.
На мой взгляд, если нужна инициалазиция, то может потребоваться и анинициализация. Как минимум в качестве хорошего стиля. Который в дальнейшем будет использован практически.
:) сейчас изучаю Пайтон, немного понял, осталось научится писать софт и подключать к нему плагины…
Подчерпнул для себя информацию, радостно и приветливо об этом сообщил в комменте, пост оказался полезен даже начинающему…

А минус то за что? :)))))))
Видимо, за «пайтон» (:
Выравнял счет.
UFO just landed and posted this here
>> sys.path.insert( 0, 'plugins') # Добавляем папку плагинов в $PATH, чтобы __import__ мог их загрузить

А по другому можно как-то? Этот метод грубый какой-то.
Чем же он грубый, вполне стандартный метод.
если бы он был стандартным, вы бы ни один иерархическую структуру скриптов не подняли.
sys.path к вашим иерархическим структурам не имеет никакого отношения, он лишь указывает интерпретатору где искать модули. Все что под вашим корневым модулем и как оно поднимается — исключительно дело вашего приложения.
он указывает у каком порядке загружать модули.
Приведите пример, в котором какие-то субмодули требуется добавлять в sys.path, а не подгружать их через __init__ родительского?
UFO just landed and posted this here
То что так кто-то делает, еще не говорит о том, что так надо делать и это правильнее, чем работа через родительский метод. Уточняю свой вопрос, приведите пример модуля, который каждый свой субмодуль зачем-то должен добавлять в path. Впрочем вы уже отчасти ответили, что это не самое лучшее решение, да и неймспейсы не зря вобщем-то придумали, к чему я автора оригинального коммента и веду.
UFO just landed and posted this here
С такими штуками главное не перейти грань, когда удобство превращается в магию)
Галиматья у вас в самом важном месте:
1. sys.path.insert — это не путь джедая, лучше в вашу папку плугинов кидать __init__.py, и портировать плагину посредством mod = __import__('plugin.foo')
2.
> __import__(os.path.splitext(s)[ 0], None, None, ['']),
у людей попроще есть только первый параметр остальное что написали это значения по умолчанию
3.
> __import__(os.path.splitext(s)[ 0], None, None, ['']),
Это вы сейчас обработали кусок неизвестного вам кода, где try except
4.
> __import__(os.path.splitext(s)[ 0], None, None, ['']),
тут же вы создали фактически аграмадную глобальную переменную тоже вам лучи поноса за это.
5.
> Plugin.__subclasses__():
может конечно это и круто, но тоже читабельности не добавляет
6.
Почему onLoad плагина не совместить бы с конструктором?

Я начал писать как-нибудь так:
for s in ss:
  print 'Found plugin', s
  mod = __import__(os.path.splitext(s)[0])
  for each in mod:
    if isinstance(Plugin, each):
      Plugins.append(each())
А я бы вместо __import__ использовал бы модуль imp
c = '' # склеиваем все аргументы в строку
for a in args:
    c += ' ' + a
c = c[1:]
print commands.getoutput( c )

что это, Бэрримор? можно (и нужно) ведь так:

print commands.getoutput (" ".join (args))

пожалуйста, не нужно писать на Питоне так, как будто пишете на brainfuck'е. это, увы, касается и предложенной вами архитектуры в целом.
Спасибо, исправил. Я недавно с питоном (:
Зачем тогда писать статьи на тему, в которой вы не разбираетесь, и вдобавок пытаетесь научить других делать плохо?
Я пропустил или тут не рассмотрена основная проблема плагинов, sandboxing?
Просто то, как подргужать планины можно много чего придумать, а вот как организовать их работу в ограниченном окружении, чтобы они не могли уронить всё приложение?
try...except в большинстве случаев вроде как достаточно
и плагин внезапно форматирует файловую систему.
В данном случае эта проблема решается на другом уровне, в виде джейлов и дедикейтед серверов, не иначе. В противном случае вам нужно написать какие-то проверяющие обертки над всеми потенциально опасными вызовами, что довольно проблематично.
UFO just landed and posted this here
UFO just landed and posted this here
Диагноз: автор не читал pep-8. def OnLoad, говорите? ну-ну
UFO just landed and posted this here
Sign up to leave a comment.

Articles