可插入的Python程序

mtk*_*358 2 python plugins qt pyqt4 pluggable

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

Ale*_*lli 6

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

接下来,如果您想允许从磁盘上的任何位置导入插件(而不是从之前添加到您的特定目录中导入插件sys.path,例如通过环境变量PYTHONPATH),您可以"正确执行"(不可忽略的工作量) ),通过标准Python库中的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)
Run Code Online (Sandbox Code Playgroud)

这不是线程安全的,因为它可能会产生副作用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)]
Run Code Online (Sandbox Code Playgroud)

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

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