Qt for Python: all the details of the latest 6.6 release 🐍


With the new Qt 6.6 release, we are happy to tell you that the project now provides all the new features and modules that Qt does, but as always, we wanted to bring extra functionality around the Python ecosystem and improve our tooling story.

You might remember the announcement for the 6.5 release, this time we spent a lot of time improving all the initial supports we described in the previous release.

You can read the full changelog here to check out all the details on the changes, but if you want to get a summary of the new features, keep reading this post.

Catching up with Qt/C++ 

Most of the work that the Qt for Python team does for each release is catching up with all the changes in the Qt API, but also, taking into account the latest C++ standards in order to offer you the same (or rather similar) set of features that Qt/C++ is bringing to the table.

The shiboken code generator has been updated to deal with more advanced C++ constructs; for example, it is now possible to declare functions with rvalue references.

Additionally, the support for more conversion operators (int, double) has been added; they translate to their Python equivalents (__int__, __float__). The __repr__ and dir() functions for smart pointers have been extended to contain information on the pointee.

Python 3.12 support

In case you didn't know, Python 3.12 has already been out since October 2nd, and we started to work on supporting it some time ago.

Currently, you will be able to use it without major problems, but new corner cases might appear. Please let us know so we can have better support!

In case you are interested in the details that took us more time: 3.12 makes the tp_dict field  PyTypeObject optional, and we were relying on that field for our __feature__ options. Even though we know that relying on that field is something that maybe CPython developers were not expecting (and might not have been encouraged), it served the purpose of our goal! Luckily for us, we could adapt our implementation to using a new internal method PyType_GetDict, but sadly, it is not part of the Stable ABI.

Python 3.7 is no longer supported

As we mentioned in the past, we made a decision not to support more than 5 Python versions, so all the efforts on supporting 3.12 imply that 3.7 will not be supported after Qt 6.6+.

In case you didn't know, by the end of June of this year, Python 3.7 reached its end of life, so in case you are tied to this version, we highly encourage you to migrate to a newer version.

New modules in PySide 

The QtGraphs module has been added to get you on the same level as the new things from Qt 6.6. This module is planned to supersede Qt Data Visualization, improving its internal implementation and replacing the OpenGL usage by relying on the Quick3D API that uses Rhi. Using Quick3D will enable you to even use Quick3D effects!

At this stage, however, it is a technical preview though; the API can be expected to change in 6.7. 

Shiboken generator is now available on PyPI

The main reason we had for skipping shiboken generator on PyPI was the dependency we have on libclang. This comes from the time that we used to have one-big-wheel for everything in the Qt for Python project.

When we split the wheels, in order to enable people to skip large modules, we noticed that the shiboken generator wheel, even after including libclang was not too large, but we kept it until some users asked for it, which was the case in the previous releases, so we are finally updating it to PyPI, meaning you can now pip install shiboken6_generator in order to get the executable to generate Python bindings to your favorite C++ project.

PySide is! - What's compatible with asyncio? 

During the 6.5 release cycle, and now with 6.6, we have been hard at work on asyncio and Qt interoperability. As you may know, asyncio lets you replace its event loop with a custom implementation, and such a custom implementation is exactly what we have been doing. This allows you to use the asyncio API and run programs that use asyncio or frameworks based on asyncio, while Qt's event loop is doing the heavy lifting. Why would we want the Qt event loop to do this? Because this puts the entire Qt API at asyncio's disposal, enabling you to mix and match code from asyncio and Qt, leveraging asyncio's async/await syntax. Today, with the first release of the 6.6 cycle, we offer a technical preview of this event loop implementation, letting you create futures, tasks, and handles, and manage the event loop lifecycle, with wide coverage of the full event loop API to be built up over the upcoming minor releases. Using Qt's event loop is as simple as adding these two lines to your code:

from PySide6.QtAsyncio import QAsyncioEventLoopPolicy



If you want to see this in action, the previously available asyncio examples have been updated to leverage this new approach, the Eratosthenes, and the Minimal one.

There is much more still to come, and we value your feedback! Be sure to let us know what you think, and don't hesitate to report any bugs you encounter.

Improving the Android compatibility 

In 6.5, we unveiled a technical preview of minimal support for Android deployment with the introduction of the tool pyside6-android-deploy. We have many updates for you for 6.6, but pyside6-android-deploy will still be in technical preview because our custom fork for python-for-android is still not merged into upstream. The tool also needs a bit more testing on our end. At Qt, we want our users to have a flawless experience with our software. We will be able to remove the 'technical preview' tag from this very soon. 

The main improvements for our Android support are the following:

  1. In 6.5, pyside6-android-deploy only supported a subset of the Qt modules (see considerations). With 6.6, we support all Qt modules available on Android platforms. This means that your PySide6 application that makes use of Qt Multimedia, Qt Bluetooth, Qt Location, etc. can be deployed to Android. The tool will automatically identify all the dependencies and package them into your generated apk.
  2. In 6.5, a pre-requisite was to manually download the Android NDK and SDK and use that to create the Android PySide6 wheels. This is now automated and can be downloaded using the cross-compilation script used to create the Android wheels. This is located within the Qt for Python repo in pyside-setup/tools/cross_compile_android/main.py. The --ndk-path and the --sdk-path options which were required in 6.5, are now optional in 6.6. The script downloads the supported Android NDK and SDK into a cache called pyside6-android-deploy located in the user's home directory. The pyside6-android-deploy tool also uses the Android NDK and SDK from this cache if available, otherwise it defaults to the ones provided by buildozer, a tool from Kivy, providing an easy interface to python-for-android.
  3. The new permission API introduced to Qt in 6.5 is now available for Android deployment in PySide 6.6. Some examples of PySide6 have already been adapted to consider this new API when deploying to Android, namely:

Most examples currently work with Android, but many of them will still have a UI that looks similar to the one for the desktop application. You can expect more examples specific to Android devices in the upcoming releases. 

Note: Android deployment only works from a Linux host due to a shortcoming of cross-compilation 

New target platform: aarch64 joins the list of supported architectures

Some time ago, we decided to start our research into embedded platforms, and you might remember that we managed to enable the cross compilation of the project for Raspberry Pi devices. 

After those devices, we wanted to extend the compatibility to other systems, but we found that it’s not a simple task to properly handle the sysroot structures, version, and many other details. Therefore, we decided to generate compatible wheels, so that end users don’t need to deal with cross-compiling the whole project. 

PySide 6.6 will be the first release to include aarch64 wheels, meaning that on embedded devices, like Raspberry Pi, you can execute pip install pyside6 to get the latest releases.

Our cross-compilation infrastructure is still around, and we will keep maintaining the process for people who rely on it.

Better access to commercial wheels 

Python developers rely on having their project dependencies on URL indexes like PyPI. However, there are also use cases where people keep their own packages or try to build some projects with exceptional cases and end up using different or self-hosted indexes. 

We noticed that many license holders were struggling a bit with getting the Qt for Python wheels from https://account.qt.io so we decided to improve the situation from different points. 

Maintenance tool

Qt License holders will now have in the Maintenance tool interface the option to select different Qt for Python versions to download the wheels locally (not installing them).


The motivation for not doing an installation is that Python projects usually rely on creating virtual environments with certain configurations for their projects, so limiting this process to the selection of an interpreter was not optimal. With the local wheels, users will be able to install them from any virtual environment.




Pip is the default package manager that you can use to install modules in your Python environment. For commercial users, this was not possible due to the nature of the PyPI repository, so we decided to wrap this tool with logic from the Maintenace Tool, creating a simple command line tool that will verify your Qt license, and provide the available commercial packages. Because this project is independent of the Qt for Python cycle, we will have a separate blog post with more details and how to install it to try it in the following days.

Qt Creator towards a better Python IDE 


The Qt Creator team has been improving the Python support for a while now, and even if their release cycle is not tied to the Qt one, we wanted to highlight a few of the things that Qt Creator currently has: 

  • The Python project templates have been adjusted, and we are currently planning to add more (if you have ideas, let us know).
  • The interpreter selection was improved. 
  • You can now create a virtual environment with your new projects using the project wizard.
  • There is automatic virtual environment detection in case you have yours already in place. 
  • If PySide6 is not installed, Qt Creator will suggest the installation of the package. 
  • If you are a commercial user and have the wheels provided by the Maintenace Tool, Qt Creator will be able to install them.

We have other features in mind, but we would love to hear from you. 

Research on dynamic bindings 

We believe that only providing a Python API on top of Qt is not enough, that is why we have been trying to offer many things "on top of Qt" in the past releases.

In past talks, you might have seen some first attempts to bring the Python interpreter to C++ applications, enabling you to evaluate Python expressions within C++. We iterated on the idea a bit and decided to tackle a similar problem, dynamic bindings.

We are currently researching a replacement for the discontinued QtScript module, which provided dynamic bindings for JavaScript in Qt 5. The new module should provide dynamic bindings for Python without the need to run the shiboken generator, which will for sure speed up the development of Python modules based on C++ libraries, but more importantly, it will encourage more people to bring C++ libraries to the Python ecosystem.

What’s next? 

We want to keep trying new experimental support, features, and Python module integration. What should we do next? Drop us a message or open a suggestion on JIRA 👍. 

We hope you enjoy the release, and as always, drop by our community platforms and let us know if something is not properly working by opening bug reports in JIRA .

Blog Topics: