我开始学习一点 Python,现在想玩弄 gui 构建。Qt 似乎是一个不错的选择,因为它具有跨平台性。
现在似乎有两个可用的绑定:Riverbank Computing 的 PyQt 和最初由诺基亚开发的 PySide。
那么我应该选择哪一个呢?我只能找到两年前的功能比较,但现在有什么不同?
哪一个更容易使用,有更多/更好的文档?两者都还在积极开发中吗?
因为我不打算编写商业应用程序,所以我不太关心许可。
6 回答
这两个工具包都得到积极维护,现在在功能和质量上或多或少相等。只有很少的,相当不重要的差异。
尽管如此,我还是推荐 Python 2 的 PySide。它有一个更合理的 API,主要是它不公开 Qt 类型,这些类型在 Python 中有直接等价物(例如 QString、QList 等),或者完全是多余的,因为Python 的动态特性,如 QVariant。这避免了许多繁琐的与 Qt 类型之间的转换,从而简化了编程并避免了许多错误。
PyQt 也支持这个现代 API,并且默认使用它用于 Python 3,但不用于 Python 2 以保持向后兼容性。
还有许可差异。PySide 是 LGPL,而 PyQt 是 GPL。如果您不想让您的项目开源,这可能会有所作为。尽管 PyQt 总是以相当合理的价格提供适当的版本。
我倾向于发现 PySide 文档更直观。在我看来,这个 API 稍微更像 Pythonic,而且目前错误修复的速度相当可观。
PyQt 具有 Python 3 支持和在职的优势。还有更多的第 3 方文档/教程。
我最近将一个重要的代码库(超过 8,000 行代码)从 PyQt 移植到了 PySide。
现在我想说 PyQt 是一个更加成熟、高性能和稳定的项目。我在 PySide 中遇到了许多错误,并且怀疑任何大型项目都会遇到问题。话虽如此,我向项目报告了一个错误,并在几周内修复并发布了新版本。我也有一个问题,应用程序需要大约 15 秒才能退出。我还没有花时间找出原因。然而,没有理由选择 PyQt 而不是 PySide 只是时间问题。
如果您现在决定使用 PyQt,请确保始终使用 API v2。它是一个更好的 API,并且将简化任何未来向 PySide 的过渡。此外,如果您进行移植,只需遵循 PySide wiki 上的指南。即使对于包含大约 20 个源文件的 8+ kloc 应用程序,它也只需要一个下午。
一个重要的事实是 PyQt4 对于某些事情有两个版本的 API。版本 1 的项目是使用QString
而不是unicode
, 和QVariant
(基本上只是一个包装,我相信 - 我实际上从未做过任何使用它的事情)而不是包装。可以在 Python 2 中启用并在 Python 3 中启用的版本 2 要好得多(尽管在许多地方仍然是 unpythonic - PySide 也是如此,但它明显变得更好。仍然存在一些与它们不兼容的地方;PyQt4 有QtCore.pyqt(Signal|Slot|Property)
, PySide 有QtCore.(Signal|Slot|Property)
.
对于我自己的一个项目,我决定在不更改代码的情况下支持两者。我更喜欢 PySide,但在 Windows 上,我使用 PyQt4 分发,因为目前它的分发要小得多。我的解决方案是检查 PySide,如果它在那里插入一个导入钩子以将 PyQt4 导入重定向到 PySide,或者如果不是,则修复 PyQt4 以使其正常工作。
使用的文件:
- pyqt4pysideimporter.py
- zip_imp.py(用于 py2exe 支持)
- make_gui.py(我的脚本,用于使用 pyside 或 pyqt4 工具构建 .ui 文件和 .qrc 文件,并修复导入以保持一致;轮询文件更改并重建更改 - 没有什么像 inotify 这样的高科技)
然后你只是import pyqt4pysideimporter
和pyqt4pysideimporter.autoselect()
(如main.py
在那个存储库中)。之后你就可以了import PyQt4
。
另外:几天前在 PySide 邮件列表上也表示,他们计划在未来几个月内完全支持 Python 3。
尽管它们可能对 Qt/C++ 类具有相似的接口,但它们对 Qt/C++ 宏(如信号/插槽/属性)的接口却大不相同。将一个移植到另一个并不是一件容易的事。最好在一开始就做出正确的决定。
除了语法/许可差异之外,我只想指出 PyQt 在语言绑定方面的一些不足,这对于用 Python 编写 QML 项目可能是必不可少的。这些差异最终将我从 PyQt 推到了 PySide。
qmlRegisterType
qmlRegisterType 对于使用 QML 创建运行时 C++ 绑定是必不可少的。在 PySide 中,它是 PySide.QtDeclarative 的一部分。这适用于 Python。
在 PyQt 中,qmlRegisterType 不存在。而且我找不到替代方法。我知道一些简单的任务可以通过设置 QML 上下文来完成。但是如果你真的需要使用 qmlRegister 和 Q_INVOKABLE 进行运行时绑定,我认为 PySide 是目前唯一的选择。
世博肯 VS SIP
两者都可以将 Qt/C++ 包装到 python 插件中。对于 Shiboken,我觉得它更简单,需要更少的编码。只需创建一个类型系统 xml,包括要导出的类的名称,仅此而已。Shiboken 不需要对目标类的结构进行额外的手动描述。
对于 SIP,它需要更多的额外编码。我们将不得不创建一个 SIP 文件,它几乎重新实现了 C++ 标头的所有内容。它不仅需要类的名称,还需要目标类具有哪些方法的详细信息。如果 C++ 类使用 Pimp 进行了良好的设计,并且我们想要导出其中的所有方法,那么 SIP 应该提供一种自动导出所有类方法的方法,而目前它还不能。这也会增加维护 SIP 和 C++ 标头之间一致性的负担。
但我不得不说,Qt wiki 上的 Shiboken 文档非常糟糕且具有误导性。在 Windows 上使用 Shiboken 创建 Python 插件根本不需要CMake。 generatorrunner也不是必需的。我只使用 windows cmd 脚本来调用 shiboken,并使用 qmake pro 来编译目标插件。
我有一个 20k 行的 Python 应用程序,但尝试转换为 PySide 失败。转换很容易,并且大多数功能都有效。有几种方法没有实现,因为它们被“弃用”,所以我不得不修复这些。那没关系。在 Windows 上,使用 PySide-1.1.2,许多 Qt 对象没有实现“==”运算符。一种解决方法是说:“如果 id(item1) == id(item2):”。另一个观察结果是 PySide 似乎明显变慢了。我没有将 PySide 隔离为缓慢的原因,但是当我恢复到 PyQt 时问题就消失了。
最后,截至目前,带有 PySide 的 Android 工具包似乎还没有准备好迎接黄金时段。