据我所知,Qt提供了两个主要的插件机制:
扩展Qt "Qt Extensions"
开发的应用程序。
我有兴趣为我的应用程序开发插件(2)。
我使用PySide,但找不到使用PySide/PyQt开发应用程序插件的任何资源。
在Q_DECLARE_INTERFACE() Qt文档之后,我了解到应用程序必须使用Q_INTERFACES()宏,插件必须同时使用Q_INTERFACES()和Q_EXPORT_PLUGIN2()宏,但我不知道它们所代表的代码试图将其转换为python。还是我错过了另一种方式?
更新:
到目前为止,我能找到的最接近解决方案的是Alex Martelli's answer to a similar question。虽然它看起来会起作用,但我宁愿使用正式的Qt方法来避免任何跨平台问题。
发布于 2012-01-30 12:45:54
我认为Qt的插件系统是为了允许人们编写编译成二进制文件的C++插件。我甚至不知道理论上是否有可能用Python编写使用类似C++二进制接口的插件。
如果您想支持Python插件,最好的选择是使用众多纯python插件系统中的一个。我编写了一个PySide应用程序,使用YAPSY加载插件脚本。YAPSY是一个非常简单、紧凑的插件模块。这是非常容易包括在您的应用程序,因为它是一个单一的文件,并是BSD许可,以便您可以使用它的商业。就在谷歌上搜索吧。我甚至能够使用py2exe打包我的应用程序,并且仍然能够从插件目录导入python源文件插件。
发布于 2021-07-21 17:43:52
我是摇滚的粉丝,你自己的方法。
我说的插件是:
我看到了插件的两个要求:
之间访问的数据。
假设
开发插件系统是非常主观的。有许多设计决策要做,没有一个真正的方式。通常的限制是时间、努力和经验。请注意,必须作出假设,并且实现常常定义术语(例如"plugin“或"package")。要善良,并尽可能最好地记录这些信息。
这个插件实现假定:
文件,要么是目录(即“插件包”)
plugin_package/ plugin_package.py <--入口点other_module.py <-+一些_subdir/x-其他文件icon.png <-+
请注意,插件包不一定是Python包。插件包是否是Python包取决于您想要如何处理导入。
相同
共享数据的主要来源
1.加载插件模块
加载插件模块需要两条信息:入口点的路径和插件的名称。如何获得这些信息可能会有所不同,获取它们通常需要字符串/路径解析。对于以下情况,假设:
plugin_path是插件入口点的绝对路径,plugin_name是插件名(由上面的assumptions).指定的模块名)。
Python已经多次实现并重新实现了导入机制。编写本报告时使用的导入方法(使用Python3.8)是:
import importlib
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader
loader = SourceFileLoader(plugin_name, plugin_path)
spec = spec_from_loader(plugin_name, loader)
plugin_module = module_from_spec(spec)
spec.loader.exec_module(plugin_module)
# Required for reloading a module
sys.modules[plugin_name] = plugin_module
# # This is how to reload a module
# importlib.reload(plugin_module)包含错误处理和加载哪些模块的记录(例如,将它们存储在dict中)可能是个好主意。为了简洁起见,这里不包括这些细节。
2.共享数据
有两个方向可以共享数据:
主模块可以在导入后免费访问插件数据(按定义)。只需访问插件模块的__dict__
# Accessing plugin data from the main module
some_data = plugin_module.__dict__.get('data')从插件内部访问主模块的数据是一个更棘手的问题。
如上所述,我通常认为QMainWindow是最终用户的“应用程序”概念的同义词。它是用户与之交互的主要小部件,因此通常包含大部分数据,或者很容易访问它。挑战是共享QMainWindow实例。
共享QMainWindow实例数据的解决方案是使其成为单个实例。这迫使任何QMainWindow成为用户交互的主要窗口。有几种方法可以在Python中创建单例。最常见的两种方法可能是使用metaclasses或模块。我使用模块单例方法获得了最大的成功。
将QMainWindow代码分解为一个单独的Python模块。在模块级别,创建但不初始化QMainWindow。创建一个模块级实例,以便其他模块可以作为一个模块属性访问该实例。不要初始化它,因为init需要一个QApplication (而且主窗口模块不是应用程序入口点)。
# main_window.py
from PySide2 import QtWidgets
class MyMainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
main_window_instance = MyMainWindow.__new__(MyMainWindow)对于应用程序入口点使用单独的模块(如main.py )。导入主窗口实例,创建QApplication,并初始化主窗口。
# main.py
import sys
# Importing the instance makes it a module singleton
from main_window import main_window_instance
from PySide2 import QtWidgets
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main_window_instance.__init__()
main_window_instance.show()
sys.exit(app.exec_())导入主窗口实例是使其成为单例的原因。在这里创建QApplication并不是绝对必要的(它也是一个单独的例子),但我觉得它更干净。
现在,当在运行时加载插件时,它们可以导入main_window_instance。因为main_window模块已经由main.py入口点加载,所以它是主模块使用的主窗口(而不是一个新实例)。现在可以从插件模块访问主模块的数据。
# plugin.py
# The plugin can now access the main module's data
from main_window import main_window_instance
main_window_instance.setWindowTitle('Changed from plugin')注释
最低设置需要三个文件:main.py、main_window.py和plugin.py。main_window.py定义并实例化主窗口,main.py使其为单例并初始化它,plugin.py导入和使用实例。
许多细节被遗漏了,希望主要的组成部分能够被清楚地显示出来。理想情况下,Qt和Python文档应该足以填补空白.
还有更多的考虑因素,比如如何分发和管理插件。插件可以远程托管,打包为(zip)存档,打包成适当的Python包等等。插件可以是您想要的简单(或复杂的)。希望这个答案能为你想让你的插件系统看上去提供足够的灵感。
https://stackoverflow.com/questions/8963528
复制相似问题