Комментарии 13
pip install importlib
Уже удивило. importlib - вообще-то встроенный модуль. Тот importlib, который лежит на pypi - клон модуля из второго питона, предназначенный для облегчения портирования старого кода.
Далее: почему os.path и ручное форматирование путей? Почему не pathlib?
Ну и закончили огрызком того, с чего стоило начать:
описать решаемый плагином круг задач (обязанности плагина)
описать интерфейс, по которому центральная программа будет обращаться к плагину
определить, какие ресурсы от центральной программы плагину потребуются
описать интерфейс, по которому центральная программа будет давать доступ к этим ресурсам
Это не только сделало бы более понятной решаемую задачу, но и повлияло бы на контроль корректности плагинов. typing.Protocol
и @typing.runtimecheckable
для описания интерфейса взаимодействия, isinstance()
для проверки, что предполагаемый класс плагина соответствует этому интерфейсу.
В общем, статья учит плохому.
Я писал статью чтобы показать, как это МОЖНО сделать и в конце статьи добавил:
"В заключение хочу сказать, что то, что мы сейчас написали - это очень плохая система"
На "описать решаемый плагином круг задач (обязанности плагина)" так же хочу сказать, что функционал и возможности плагина придумывает сам разработчик плагина.
А в остальном в следующий раз обязательно учту ваши замечания. Спасибо за конструктивную и обоснованную критику!
функционал и возможности плагина придумывает сам разработчик плагина.
Увы, это не до конца так. Чтобы возможности у плагина были, основная программа должна предоставлять те или иные интерфейсы доступа к себе: возможность банально вызвать/отреагировать на какое-то событие, разместить новые элементы в GUI, получить доступ к каким-то структурам данных, и т.п.
А это надо предусмотреть заранее, потому что если плагинам приходится лезть в основную программу через рефлексию, и monkey-patch'ить происходящее в ней, то проблемы с совместимостью плагинов между собой и с разными версиями программы, считай, гарантированы.
Если кому нужно - я поддерживаю библиотеку Python, которая позволяет делать плагинные системы: https://github.com/janvarev/jaapy
Используется в голосовом помощнике Ирина (700+ звезд на Гитхабе) для плагинов, в OneRingTranslator (универсальный REST-интерфейс для разных переводчиков), и еще у меня кое-где. Полет нормальный, рекомендую.
Как вы её пропихнули в проекты вообще без тестов, особенно слияние конфигов?
Из примера не понятно как работать.
Вот вызвал я main.init_plugins()
и что дальше произойдёт? Вызовется какой-то удалённый код и всё, или я смогу получить объект и его как-то использовать?
Не очень понимаю, что непонятно - в demo примерах есть примеры использования, например, как написать интерпретатор команд пользователя, где команды подключаются плагинами.
Если этот код из примера непонятен, я уже не знаю, как написать проще:
# Demo 0
# start function
def start(core):
manifest = {
"name": "Demo 1 cmd",
"version": "1.0",
"cmds": {
"hello": run_hello,
}
}
return manifest
def run_hello(core,params):
print("Hello, world!")
Если этот код из примера непонятен, я уже не знаю, как написать проще:
В коде нет действия. Что делают сами функции понятно, а вот зачем они здесь нет.# Demo 0
Не информативно, напишите например Демо плагина который печатает текст на консоль# start function
Не далайте так пожалуйста, те кто читают этот файл знают что def start
это # start function
. Это дублирование информации. Напишете что эта функция будет вызванна при инициализации плагина. def run_hello(core,params):
Я бы переименовал в _run_hello
, нижнее подчёркивание это конвенция для внутренних функци, в данном примере эта функция не важна.
Мой комментарий был про пример в документации. main.init_plugins()
что здесь должно прозойти? Просто распишите, что в папке найдутся файлы и они выполнятся и вы увидете "Hello, world!"
.
Нарушено много правил хорошего кода (pep-8)
Скажите мне зачем нарушать pep8? Он стандарт по умолчанию и есть много инструментов которые вам всё расскажут и покажут что нужно исправить и некотрые даже поправят тривиальные вещи. Просто возьмите себе за правило прогонять линтеры и форматеры на любом коде который видят другие люди.
то учитывайте все эти факторы при написании кода.
Я бы еще добавил один момент, это безопастность. Вы ставляете плагин внутрь своего приложения и даёте ему доступ ко всей памяти. Чужой код так может быть выполнять опасно.
В своё время делал механизм плагинов для упрощения разработки.
Описание и плагины
https://github.com/freeorion/freeorion/tree/master/default/python/handlers
Загрузчик плагинов
https://github.com/freeorion/freeorion/blob/367dbe1ef3d3237f7c621a824b49e8e4e0a991f0/default/python/common/handlers.py#L10
Декоратор для точки входа
https://github.com/freeorion/freeorion/blob/367dbe1ef3d3237f7c621a824b49e8e4e0a991f0/default/python/common/listeners.py#L37
В итоге выжил только плагин который по модулю существующему только в рантайме (C++ binding) создаёт файл с питоновскими скелетам (.pyi). Скелеты позволяют иметь автоподстановку в IDE.
@nickname235342, можно еще покапаться в коде Django.
Там можно подключать собственные модули через конфиг "'ENGINE': 'path.to.custom.backend.NoSQLDatabaseWrapper'
https://reintech.io/blog/writing-custom-database-backends-in-django-tutorial
Настройки тоже динамические.
Когда вы запускаете сервер, то в рантайме выбирается реальный файл с настройками, а доступен он будет через from django.conf import settings. Не совсем планин, но есть сходство. https://docs.djangoproject.com/en/5.0/topics/settings/#using-settings-in-python-code
Python: Как написать систему модов для игры / плагинов для программы