Question or problem about Python programming:
I started learning a bit of python and would now like to toy around a bit with gui-building. Qt seems to be a good choice because of its cross-platformishness.
Now there seem to be two bindings available: PyQt by Riverbank Computing and PySide, originally developed by Nokia.
So which one should I choose? All I can find are two year old feature comparisons, but what differences are there nowadays?
Which one is easier to use, has more/better documentation? Are both still in active development?
Licensing isn’t of much concern to me since I don’t intend to write commercial applications.
How to solve the problem:
Both toolkits are actively maintained, and by now more or less equal in features and quality. There are only few, rather unimportant differences.
Still, I’d recommend PySide for Python 2. It has a more reasonable API, mainly it doesn’t expose Qt types, which have a direct equivalent in Python (e.g. QString, QList, etc.) or which are completely superfluous due to Python’s dynamic nature, like QVariant. This avoids many tedious conversions to and from Qt types, and thus eases programming and avoids many errors.
PyQt also supports this modern API, and uses it by default for Python 3, but not for Python 2 to maintain backwards compatibility.
There is also the licensing difference. PySide is LGPL while PyQt is GPL. This could make a difference if you don’t wish to make your project opensource. Although PyQt always has the propriety version available for a fairly reasonable price.
I tend to find the PySide documentation more intuitive. The API, in my opinion is slightly more Pythonic and the rate of bug fixes is quite impressive at the moment.
PyQt has the advantage of Python 3 support and incumbency. There is a lot more 3rd party documentation/tutorials for it.
I recently ported a significant code base (over 8,000 lines of code) from PyQt to PySide.
Right now I’d say PyQt is a much more mature, performant and stable project. I hit a number of bugs in PySide, and suspect that any big project will hit issues. Having said that, I reported a bug to the project and it was fixed and in a new release within a few weeks. I’m also having a problem where the app takes about 15 seconds to quit. I’ve not yet spent the time to find out why. However it’s only a matter of time before there will be no reasons for choosing PyQt over PySide.
If you do decide to go with PyQt for now, make sure you use API v2 throughout. It is a better API, and will ease any future transition to PySide. Also if you do port, just follow the guidelines on the PySide wiki. Even for an 8+ kloc app consisting of about 20 source files it just took an afternoon.
An important fact is that PyQt4 has two versions of its APIs for some things. Version 1 items are such things as using
QString instead of
QVariant (basically just a wrapper, I believe – I’ve never actually done anything which uses it) instead the wrapped. Version 2, which can be enabled in Python 2 and is enabled in Python 3, is much better (though still unpythonic in many places – PySide is too, but it’s getting distinctly better. There are still some remaining incompatibilities with them; PyQt4 has
QtCore.pyqt(Signal|Slot|Property), PySide has
For a project of my own, I decided that I wanted to support both with no changes to the code. I prefer PySide, but on Windows I distribute with PyQt4 as at present it’s quite a bit smaller for distribution at present. My solution is to check for PySide and if it’s there insert an import hook to redirect PyQt4 imports to PySide, or if it’s not, fix up PyQt4 to work like it should.
The files used:
- zip_imp.py (for py2exe support)
- make_gui.py (my script for building .ui files and .qrc files with pyside or pyqt4 tools, and fixing the imports to be consistent; polls for file changes and rebuilds the changed – nothing high tech like inotify)
Then you just
import pyqt4pysideimporter and
pyqt4pysideimporter.autoselect() (as in
main.py in that repository). And after that you can just
Aside: it was also stated a few days ago on the PySide mailing list that they are planning on supporting Python 3 fully within the next few months.
Although they might have similar interface for Qt/C++ classes, their interface for Qt/C++ macros such as signal/slot/property are very different.
Porting one to another is not an easy job. It would be better to make the right decision at the very beginning.
Beyond the grammar/license differences, I just want to point out some deficiency of PyQt in language binding, which might be essential to write QML project in Python.
These differences finfally push me to PySide from PyQt.
qmlRegisterType is essential to create runtime C++ binding with QML.
In PySide, it is part of PySide.QtDeclarative. And this works pretty well with Python.
In PyQt, qmlRegisterType does not exist. And I could not find an alternative approach.
I know some simple task could be done by setting QML context.
But if you really need runtime binding with qmlRegister and Q_INVOKABLE, I think PySide is the only choice at the moment.
Shiboken VS SIP
Both can wrap Qt/C++ into python plugin.
For Shiboken, I feel it is simpler and requires less coding.
Just create a typesystem xml including the NAME of classes you want to export, and that’s all.
Shiboken does not require extra manual descriptions for the structure of the target classes.
For SIP, it would require more extra coding. We will have to create a SIP file that almost reimplements everything the C++ header.
It requires not only the NAME of the class, but also the DETAILS of what methods the target classes have.
If the C++ class is in good design using Pimp and we want to export all methods within it, SIP should provide a way of automatically export all class methods, which it cannot at the moment.
This would also add the burden for maintaining the consistency between the SIP and the C++ headers.
But I have to say that the documentation for Shiboken on Qt wiki is very bad and misleading.
Creating Python plugin with Shiboken on Windows do not necessarily require CMake at all.
generatorrunner is also not required.
I only use a windows cmd script to invoke shiboken, and a qmake pro for compiling the target plugin.
I have a 20k line Python app that I unsuccessfully tried to convert to PySide.
Conversion is easy and most of the functionality works.
There are several methods that are not implemented because they are ‘deprecated’, so I had to fix those. That was OK.
On Windows, using PySide-1.1.2, the ‘==’ operator is not implemented for many Qt objects. One workaround is to say: “if id(item1) == id(item2):”.
The other observation is that PySide seemed noticeably slower. I did not isolate PySide as the cause of the slowness, but the problem went away when I reverted back to PyQt.
Lastly, as of now, the Android kit with PySide does not seem ready for prime time.