Скорая Компьютерная Помощь г. Калуга

Полный спектр компьютерных услуг!

Здравствуйте, гость ( Вход | Регистрация )

> Внимание!

  • Вся информация, расположенная в данном и других разделах форума получена из открытых источников (интернет-ресурсы, средства массовой информации, печатные издания и т.п.) и/или добавлена самими пользователями. Администрация форума предоставляет его участникам площадку для общения / размещения файлов / статей и т.п. и не несет ответственности за содержание сообщений, а также за возможное нарушение авторских, смежных и каких-либо иных прав, которое может повлечь за собой информация, содержащаяся в сообщениях.
Ремонт компьютеров в калуге Рекламное место сдается
 
Ответить в эту темуОткрыть новую тему
> [Из песочницы] Плагины в кармане или перочинный ножик в программе
Decker
сообщение 11.4.2016, 13:23
Сообщение #1


Администратор
*****

Группа: Главные администраторы
Сообщений: 14349
Регистрация: 12.10.2007
Из: Twilight Zone
Пользователь №: 1




Python*


В этой статье речь пойдет о плагинах — программных модулях, которые можно легко установить в основное приложение для расширения его функционала. Точнее, не о самих плагинах, а о том, как реализовать в своей программе систему взаимодействия "Приложение — Плагин".



В сети можно легко найти достаточно сложные и, порой, запутанные алгоритмы интеграции в ваш программный код подобной системы, но, поскольку мы будем использовать язык программирования Python, для нас все будет просто и предельно ясно.



Однако перед тем как показать читателю все инструменты своей плагинной системы — своего рода перочинный ножик, который по моему мнению, должен быть в каждом уважающем себя кармане, пардон, программе — немного предыстории...



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



После этого я твердо решил пересмотреть архитектуру своих проектов и, дабы не наступать на одни и те же грабли, поставил для себя задачу: расширение возможностей моих программ должно производиться в один клик! Сказанно — сделанно.



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







И пересчитаем его косточки:



Папка Libs предназначена для библиотек и модулей будущего проекта. На данный момент в ней находятся модули для инициализации и подключения плагинов:



loadplugin.py — загружает плагины программы из папки Plugins (будет создана автоматически) корневой директории проекта;

manifest.py — класс, описывающий манифест загружаемого плагина;



В корневой директории проекта:



program.py — основной рограммный код приложения, находящийся в классе Program;

main.py — запускает программный код program.py и подключает плагины, если таковые имееются;



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



main.py:



#! /usr/bin/python2.7
# -*- coding: utf-8 -*-

import traceback

__version__ = "0.0.1"

def main():
try:
from Libs.loadplugin import loadplugin # функция загрузки плагинов
from program import Program # импортируем основной класс программы

app = Program()
loadplugin(app) # загружаем плагины
app.run() # запуск приложения
except Exception as exc:
print traceback.format_exc()
traceback.print_exc(file=open("error.log", "w"))

# Вывод окна с текстом ошибки.

if __name__ "__main__":
main()

Алгоритм модуля main.py:



  1. Создаем экземпляр app класса Program и передаем его в функцию загрузки плагинов (данный экземпляр будет доступен всем подключаемым плагинам, предоставляя им доступ к переменным и функциям, реализованным в основном программном коде класса Program).
  2. Загружаем плагины.
  3. Запускаем приложение.
  4. Выводим окно с текстом ошибки, если таковая возникла при запуске программы.


loadplugin.py:



# -*- coding: utf-8 -*-

import os
import traceback

def loadplugin(app):
"""Загружает плагины.

:type app: <class 'program.Program'>;
:param app: экземпляр класса Program;

"""

# Директория плагинов.
plugins_path =
"{}/Plugins".format(os.path.split(os.path.abspath(sys.argv[0]))[0])
# Список разрешенных к подключению плагинов.
plugin_list =
eval(open("{}/plugins_list.list".format(plugins_path)).read())

for name in os.listdir(plugins_path):
if name.startswith("__init__."):
continue

path = os.path.join(plugins_path, name)
if not os.path.isdir(path):
continue

try:
if name in plugin_list:
execfile(os.path.join(path, '__init__.py'),
{"app": app, "path": path})
except Exception:
raise Exception(traceback.format_exc())


Алгоритм модуля loadplugin.py:



  1. Сканируем директорию (пакет) Plugins на присутствие пакетов плагинов (любой python-пакет в папке Plugins будет считаться плагином).
  2. Инициализируем список плагинов из файла plugins_list.list, который находится в директории Plugins.
  3. Если найденный плагин упомянут в данном списке, подключаем его, в противном случае ищем следующий плагин.


Для большей наглядности я убрал из модуля loadplugin.py верефикацию плагинов и различные проверки на отсутствие директории Plugins, файла plugins_list.list и пр.



Как вы заметили, плагин исполняется функцией execfile:



execfile(os.path.join(path, '__init__.py'),
{"app": app, "path": path})

которая выполняет код файла [b]init.py[/b] пакета плагина и передает в глобальное пространство имен [b]init.py[/b] экземпляр app главного класса приложения.



Далее, через app, плагин получает доступ ко всем функциям и переменным программного кода приложения. Довольно просто.



Теперь давайте перейдем от слов к делу и запустим тестовый пример (main.py) из папки TestPlugin.



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



Итак, запустив пример, увидим простенький интерфейс с actionbar внизу экрана. Выберем кнопку в нижнем правом углу, открыв выпадающий список из двух пунктов, нажимаем пункт "Плагины" и читаем сообщение "Нет установленных плагинов".







Действительно, заглянув в папку проекта, обнаружим новую директорию Plugins.







Кроме уже известных нам файлов, директория для плагинов пуста. Ну что ж! Самое время их установить. Давайте расширим инструментал нашего перочинного ножика с помощью плагина и добавим в actionbar новую кнопку с логотипом Хабра.



В архиве с тестовым примером, помимо проекта TestPlugins, имеется папка Plugins. Откройте ее и скопируйте плагин HabraButton в проект в директорию Plugins.







Теперь снова запускаем наше тестовое приложение и выбираем пункт "Плагины".







Ура! Наш перочинный ножик только что обзавелся новеньким инструментом, как и было обещанно, в один клик.



Пункт с именем свежего плагина горит желтым цветом, это значит, что приложение его опознало, но не подключило к использованию. Исправляем это, нажимая на кнопку с найденным плагином.







Подключаем плагин, читаем сообщение, что "Плагин подключен и будет импортирован в проект после следующего запуска."



Если снова выбрать в выпадающем списке пункт "Плагины", увидим, что, действительно, плагин успешно падключен, о чем свидетельствует кнопка, горящая уже голубым цветом.







Собственно, что произошло, когда мы выбрали пункт "Подключить"? Имя плагина было добавлено в список разрешенных к использованию в файл plugins_list.list в директории Plugins. Теперь модуль загрузки плагинов loadplugin.py сможет импортировать данный плагин.



Давайте это проверим и запустим тестовый пример еще раз.







Появилась новая кнопка с логотипом Хабра в actionbar. Нажимаем ее и наслаждаемся сообщением "Привет, плагин"!



Вот, собственно, и все.



Я не рассматриваю в данной статье код самого плагина (он довольно прост). Вы можете открыть файл [b]init.py[/b] пакета HabraButton и посмотреть, как через экземпляр app плагин обращается к объектам программного кода класса Program. Также за бортом я оставил верефикацию плагинов. Мне она нужна, чтобы отслеживать совместимость и визуализировать информацию о плагинах. Все это есть в тестовом примере.



Надеюсь, смог быть полезным!



Тестовый пример — 40.65 Kb.



Original source: habrahabr.ru (comments, light).

Читать дальше


--------------------

Вернуться в начало страницы
 
+Ответить с цитированием данного сообщения

Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

Рекламное место сдается Рекламное место сдается
Текстовая версия Сейчас: 29.1.2025, 23:52
Рейтинг@Mail.ru
Яндекс.Метрика Яндекс цитирования