可插入的Python程序

发布于 2024-09-16 05:04:20 字数 98 浏览 5 评论 0原文

我想制作一个支持插件的PyQt4程序。基本上,我希望用户能够在 PyQt4 中编写 QWidget 子类,并通过 GUI 从主应用程序窗口添加/删除它们。我该怎么做,特别是插件机制?

I want to make a PyQt4 program that supports plugins. Basically I want the user to be able to write QWidget subclasses in PyQt4 and add/remove them from the main application window via a GUI. How would I do that, especially the plugin mechanism?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白衬杉格子梦 2024-09-23 05:04:20

首先,使用 QFileDialog 或更方便的静态函数QFileDialog.getOpenFileName 让用户选择他们想要“插入”您的 GUI 的 .py 文件。

接下来,如果您希望允许从磁盘上的任何地方导入插件(而不是从之前添加到 sys.path 的特定目录,例如通过环境变量) PYTHONPATH),您可以通过 imp 模块),或者您可以按如下方式“偷工减料”(假设 filepathQString ,其中文件的路径,并且您正在使用具有本机 Unicode 文件名的文件系统/平台 - 否则您必须添加您的平台和文件系统所需的任何 .encode )...:

import sys, os

def importfrom(filepath):
    ufp = unicode(filepath)
    thedir, thefile = os.path.split(ufp)
    if sys.path[0] != thedir:
      sys.path.insert(0, thedir)
    themodule, theext = os.path.splitext(thefile)
    return __import__(themodule)

这不是不是线程安全的,因为它可能会对 sys.path 产生副作用,这就是为什么我说它是“偷工减料”......但是,进行线程安全导入(并且“干净”)从“任何地方”导入)是真正艰苦的工作(如果需要,可能值得单独提出一个问题,因为它实际上与这个或 PyQt 的要点没有多大关系,&c) 。

一旦你有了模块对象(上面 importfrom 的结果),我建议:

from PyQt4 import QtGui 
import inspect

def is_widget(w):
    return inspect.isclass(w) and issubclass(w, QtGui.QWidget)

def all_widget_classes(amodule):
    return [v for n, v in inspect.getmembers(amodule, is_widget)]

这将返回一个列表,其中包含定义的所有小部件(如果有)(在顶部) level) 在模块 amodule 中。

当然,接下来你想做什么取决于你。也许您想在列表为空时给出某种错误消息(或者如果列表有多个项目?或者如何决定使用哪个小部件类?)或者实例化小部件类(多少次?在什么坐标?等等 - 只有您可以回答的问题)并在窗口上的适当位置显示生成的小部件。

First, use a QFileDialog or more conveniently the static function QFileDialog.getOpenFileName to let the user pick the .py file they want to "plug into" your GUI.

Next, if you want to allow importing the plugin from anywhere on the disk (as opposed to, from specific directories previously added to your sys.path, e.g. via the environment variable PYTHONPATH), you can "do it right" (a non-negligible amount of work), via the imp module in the standard Python library), or you can "cut corners" as follows (assuming filepath is the QString with the path to the file, and that you're using a filesystem/platform with natively Unicode filenames -- otherwise you'll have to add whatever .encode your platform and filesystem require)...:

import sys, os

def importfrom(filepath):
    ufp = unicode(filepath)
    thedir, thefile = os.path.split(ufp)
    if sys.path[0] != thedir:
      sys.path.insert(0, thedir)
    themodule, theext = os.path.splitext(thefile)
    return __import__(themodule)

This isn't thread-safe because it may have a side effect on sys.path, which is why I said it's "cutting corners"... but then, making thread-safe imports (and "clean" imports from "anywhere") is really hard work (probably worth a separate question if you need to, since it really has nothing much to do with the gist of this one, or PyQt, &c).

Once you do have the module object (the result from importfrom above), I suggest:

from PyQt4 import QtGui 
import inspect

def is_widget(w):
    return inspect.isclass(w) and issubclass(w, QtGui.QWidget)

def all_widget_classes(amodule):
    return [v for n, v in inspect.getmembers(amodule, is_widget)]

This returns a list with all the widget classes (if any) defined (at the top level) in module amodule.

What you want to do next is up to you, of course. Perhaps you want to give some kind of error messages if the list is empty (or maybe also if it has more than one item? or else how do decide which widget class to use?) or else instantiate the widget class (how many times? At what coordinates? And so on -- questions only you can answer) and show the resulting widget(s) in the appropriate spot(s) on your window.

隐诗 2024-09-23 05:04:20

拥有一个插件目录,为这些插件定义一个接口,然后遍历目录导入它们。

我从未在 Python 中这样做过,但在 C 中,我的做法是定义插件需要实现的许多函数。必要的基本关键元素是插件中事物的名称(以便您可以在 UI 中显示它们,以便用户可以实例化它们)和实际创建事物的工厂。我想在 Python 中,将这些作为一个可以从模块返回的指令来执行是非常简单的。

例如,声明所有插件必须编写一个名为 GetPluginInfo() 的函数,该函数返回名称:类映射的字典。

实际上,现在我想到了,您可能只需导入文件并查找属于您关心的任何内容的子类的类,而不需要实现任何显式 API。我没有做很多这样的事情,但基本上你会遍历模块的 dir() 并测试看看每个东西是否都是 QWidget 的子类(例如)。

Have a directory for the plugins, define an interface for those plugins, and walk the directory importing them.

I've never done this in Python, but in C the way I did it was to define a number of functions that the plugin needed to implement. The basic key elements that are necessary is the name of the things in the plugin (so that you can display them in your UI so that the user can instantiate them) and a factory to actually create the things. I suppose in Python it'd be pretty trivial to just do those as one dict that you can return from the module.

E.g. declare that all plugins must author a function called GetPluginInfo() which returns a dictionary of name:class mappings.

Actually now that I think about it you could probably just import the file and look for classes that are subclasses of whatever you care about and not require any explicit API be implemented. I haven't done a lot of that but basically you'd walk the module's dir() and test to see if each thing is a subclass of QWidget (for example).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文