首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何开发PySide应用程序插件?

如何开发PySide应用程序插件?
EN

Stack Overflow用户
提问于 2012-01-22 18:34:13
回答 2查看 1.5K关注 0票数 2

据我所知,Qt提供了两个主要的插件机制:

扩展Qt "Qt Extensions"

  • Plugins的
  1. 插件,该插件扩展了使用Qt

开发的应用程序。

我有兴趣为我的应用程序开发插件(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方法来避免任何跨平台问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-30 12:45:54

我认为Qt的插件系统是为了允许人们编写编译成二进制文件的C++插件。我甚至不知道理论上是否有可能用Python编写使用类似C++二进制接口的插件。

如果您想支持Python插件,最好的选择是使用众多纯python插件系统中的一个。我编写了一个PySide应用程序,使用YAPSY加载插件脚本。YAPSY是一个非常简单、紧凑的插件模块。这是非常容易包括在您的应用程序,因为它是一个单一的文件,并是BSD许可,以便您可以使用它的商业。就在谷歌上搜索吧。我甚至能够使用py2exe打包我的应用程序,并且仍然能够从插件目录导入python源文件插件。

票数 4
EN

Stack Overflow用户

发布于 2021-07-21 17:43:52

我是摇滚的粉丝,你自己的方法。

我说的插件是:

  • Plugin:运行时加载的模块或包,它增强或修改主模块的行为

我看到了插件的两个要求:

  1. 可以在运行时加载插件吗?
  2. 是在主模块和插件

之间访问的数据。

假设

开发插件系统是非常主观的。有许多设计决策要做,没有一个真正的方式。通常的限制是时间、努力和经验。请注意,必须作出假设,并且实现常常定义术语(例如"plugin“或"package")。要善良,并尽可能最好地记录这些信息。

这个插件实现假定:

  • 插件要么是

文件,要么是目录(即“插件包”)

  • 插件包是一个具有结构的目录:

plugin_package/ plugin_package.py <--入口点other_module.py <-+一些_subdir/x-其他文件icon.png <-+

请注意,插件包不一定是Python包。插件包是否是Python包取决于您想要如何处理导入。

  • 插件名与插件入口点的文件名以及插件包目录

相同

  • QApplication的QMainWindow是从主模块

共享数据的主要来源

1.加载插件模块

加载插件模块需要两条信息:入口点的路径和插件的名称。如何获得这些信息可能会有所不同,获取它们通常需要字符串/路径解析。对于以下情况,假设:

  • plugin_path是插件入口点的绝对路径,
  • plugin_name是插件名(由上面的assumptions).

指定的模块名)。

Python已经多次实现并重新实现了导入机制。编写本报告时使用的导入方法(使用Python3.8)是:

代码语言:javascript
复制
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__

代码语言:javascript
复制
# 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 (而且主窗口模块不是应用程序入口点)。

代码语言:javascript
复制
# 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,并初始化主窗口。

代码语言:javascript
复制
# 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入口点加载,所以它是主模块使用的主窗口(而不是一个新实例)。现在可以从插件模块访问主模块的数据。

代码语言:javascript
复制
# 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.pymain_window.pyplugin.pymain_window.py定义并实例化主窗口,main.py使其为单例并初始化它,plugin.py导入和使用实例。

许多细节被遗漏了,希望主要的组成部分能够被清楚地显示出来。理想情况下,Qt和Python文档应该足以填补空白.

还有更多的考虑因素,比如如何分发和管理插件。插件可以远程托管,打包为(zip)存档,打包成适当的Python包等等。插件可以是您想要的简单(或复杂的)。希望这个答案能为你想让你的插件系统看上去提供足够的灵感。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8963528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档