Featured image 6 minutes read

In this article, you will learn the differences between PyQt and Qt for Python PySide2 so you can decide which Python Qt binding you want to use.

Why two Python Qt bindings?

When reading this article, you will probably be confused about why there are two Python bindings for the Qt GUI framework and not only one. To understand this phenomenon we have to take a look Qt's history.

PyQt exists for a long time and is supported by Riverbank Computing Limited, a small (one-person?) consulting firm. Back in the days when Qt was owned by Nokia, Nokia decided to create their own Qt binding PySide. The reason for this is very likely that PyQt is licensed under GPL and a commercial license.

Unfortunately, Nokia was bought by Microsoft and Qt, which primarily used to develop GUIs for Symbian, was sold to Digia. Since then, PySide was solely supported by the open source community and for the most part, lacked behind PyQt.

Christian Tismer picked up the work on Qt5 support in PySide2 in 2015 for AutoDesk and created a first merely usable version. In 2016, the project was internally picked up by the Qt Company.

In 2018, support for PySide2 was officially announced up by the Qt Company, the official company behind Qt. At the end of 2018, the first version of Qt for Python, the new name for PySide2, was released.

Differences

For the most part, PyQt5 and PySide2 are very similar. The Qt for Python API is even designed to be compatible with PyQt5.

Moreover, I'm going to explain the difference in the following areas in detail.

  • License
  • API completeness
  • Tools
  • Community and support
  • Binding generator

License

The most significant difference between PyQt5 and PySide2 is the license. PyQt5 is released under the GNU GPL v3 and the Riverbank Commercial License. Qt for Python is available under the LGPL v3 and the Qt Commercial License.

The PyQt5 commercial license costs 550$ net with one year support. The price for a commercial Qt license varies depending on the size of your company and your application.

What does this mean for your application? If you are developing open-source software, for the most part, it doesn't matter. However, in some cases, for example, when you want to build an open-source application that can be used in closed-source commercial projects, it may be significant that the dependency libraries don't use the GPL.

When you are working on a commercial application, however, it does matter if you select the GPL, LGPL or any of the commercial licenses. With the GPL you will need to publish the source code of your application and, more importantly, your application also needs to be licensed under a GPL compatible license. For most commercial applications this is unacceptable.

The LGPL however, allows you to distribute your closed-source application along with instructions on how to replace the library.

The commercial license allows you to distribute your application without requiring any instructions. This especially important for embedded devices, when you intend to lock down the users' access to the file system.

However, be aware that the Riverbank Commercial License is only applicable to the Python binding and not Qt itself. So in case you intend to lock down your application, you may need to buy a commercial license for Qt additionally.

Therefore, in my opinion, Qt for Python strongly wins when it comes to licensing.

Tools and Add-ons

The tools that come with the Python Qt binding are rarely discussed when comparing PyQt and Qt for Python.

Some tools

PyQt comes with a whole range of tools. One of the most interesting ones is the pyqtdeploy tool, which claims to be able to deploy PyQt applications for Windows, Linux, OS X, Android and, even iOS.

I have tested the tool, and it seems to work for desktop platforms. However, I couldn't get it to work correctly for Android, due to lack of sufficient documentation.

Moreover, PyQt comes with additional add-ons and libraries including QScintilla2 and dip. Most of the libraries seem to be focused on the use with Qt widgets.

PySide2 currently has no dedicated deployment tool.

PyQt wins when it comes to tools. However, the difference might be insignificant if you use the Python binding to work with Qt Quick.

API Completeness

When it comes to the API, PyQt5 is very similar to PySide2. However, from my experience, I know that both bindings have their flaws.

Qt for Python is still relatively new, and therefore, some essential API functions, including for example qmlRegisterSingletonType are still missing.

From my experience with PyQt5, I also know that QML related features might be missing or untested. For example, I recently discovered that QValidator implementations in Python registered to QML don't work.

Overall, I would say PyQt5 wins this battle compared to PySide2.

Community and Support

An important factor when choosing an open source project or any dependency library over another is the community and support behind the project.

Here PyQt and Qt for Python significantly differ. From a community standpoint, PyQt probably has a larger community. However, the development process doesn't seem to be very open, and it is lead by a single entity.

Community

PySide has lost most of the community from the Nokia days, but since it has been picked up as official Qt binding for Python, it's very likely that the community will quickly catch up. The development process is open and very close to the development process of Qt.

Commercial support for PyQt is cheaper than the commercial support for Qt for Python. However, which quality of support is given, is unclear. The Qt Company, on the other hand, can provide support for all types of customers, including project-based consulting and on-site support.

Also important to notice is the fact that the supporting company behind PyQt, Riverbank Computing, is a tiny company, probably only one person. We hope that it will not happen, but if he/she gets hit by a bus, you are out of luck.

Qt for Python clearly wins this point.

Binding Generator

d
Which Python C/C++ binding generator the binding uses might not be relevant to you if you want to use the library without adding any additional C++ libs. However, if you plan to access an extra C or C++ library from Python, then the choice of the Python binding generator might be relevant to you.

PyQt comes with the SIP binding generator.

PySide comes with the Shiboken binding generator.

From the results, the most critical difference is that bindings generated by Shiboken can accept any kind of input, whereas SIP generated bindings only take types which are known by SIP.

Moreover, SIP can be used to generate Python bindings for C as well as C++ libs. Shiboken, on the other hand, is designed to work with C++.

How to create custom bindings with SIP and Shiboken strongly differs. Let's take a look at a short example.

// Define the interface to the word library.

class Word {
const std::strin the_word;

public:
Word(const std::string &w);

std::string reverse() const;
};

The SIP specification looks as follows:

// Define the SIP wrapper to the word library.

%Module word

class Word {

%TypeHeaderCode
#include <word.h>
%End</word.h>

public:
Word(const std::string &w);

std::string reverse() const;
};

As you can see, the SIP specification code is mostly copy-and-paste of the actual C++ code. Most importantly, every function which should be exposed needs to be defined.

The Shiboken code, on the other hand, looks as follows:

#ifndef BINDINGS_H
#define BINDINGS_H
#include "word.h"
#endif // BINDINGS_H
<!--?xml version="1.0"?-->
<typesystem package="Universe">
     <primitive-type name="std::string">
     <object-type name="Word">
</object-type>
</primitive-type></typesystem>

We have a bindings header file and an XML file specifying a type system. Shiboken generates the API functions automatically generated from the C++ code.

Which binding generator to choose might be personal preference. However, from a maintenance standpoint, Qt for Python wins his battle.

Wrappers

PyQt and Qt for Python both have its advantages and disadvantages. As of the beginning of 2019, the choice between PySide2 and PyQt is not easy to decide.

Luckily, the APIs of PyQt and Qt for Python are very similar. A couple of projects already take advantage of this fact and provide a small abstraction layer over both libraries.

The most popular one is probably QtPy, I use python_qt_binding, the wrapper used in ROS, in most of my projects. python_qt_bindings additionally provides a small CMAKE shim for Shibokem and SIP. This important for projects such as RViz which provide Python bindings for PyQt and PySide.

Conclusion

In this blog post, you learned about the difference between PyQt5 and PySide2 (aka Qt for Python). The side-by-side comparison of the advantages and disadvantages will make it easier for you to decide which Python binding for Qt to choose.

If you don't want to invest too much in one or the other, you can use one of the present wrappers. Using a wrapper is also my preferred choice for current projects.

Your
Machine Koder