Solved Packaged Qt/Python applications on Windows : what do I really need
-
Hi,
I am working on a small PyQt application and I packaged it under Windows. I was quite shocked by the initial size of the resulting package : 76 Mbytes ! For an application of hardly 10 000 lines !
When looking at the files, there are a few easy wins, like removing the DLL of the modules which I don't use, like Qt5Network, Qt5Quick and so on. I don't know why they get included if the linked pyd is not included.
The next interesting easy wins are in the pyside2/plugin directory :
$ find . . ./bearer ./bearer/qgenericbearer.dll ./iconengines ./iconengines/qsvgicon.dll ./imageformats ./imageformats/qgif.dll ./imageformats/qicns.dll ./imageformats/qico.dll ./imageformats/qjpeg.dll ./imageformats/qsvg.dll ./imageformats/qtga.dll ./imageformats/qtiff.dll ./imageformats/qwbmp.dll ./imageformats/qwebp.dll ./platforminputcontexts ./platforminputcontexts/qtvirtualkeyboardplugin.dll ./platforms ./platforms/qminimal.dll ./platforms/qoffscreen.dll ./platforms/qwebgl.dll ./platforms/qwindows.dll ./platformthemes ./platformthemes/qxdgdesktopportal.dll ./styles ./styles/qwindowsvistastyle.dll
This is where I would be happy to receive some guidance.
My limited analysis is the following :
-
bearer : this is highly linked to QtNetwork. So, no need to include it if you are not using QtNetwork at all.
-
iconengines : loading SVG is nice, but I don't do it. This one can probably go as well
-
imageformats : nice, many supported image types. But I only use resources in .ico and .png format. So all the others can go away. SVG is present here as well, which makes me think that iconengine and image loading are two separate things
-
platforminputcontext : I just have no idea what this is and when it is used. On Android or other devcies with no keyboard ?
-
platforms : this one leaves me really skeptical. We are on Windows as the DLL extension can attest, why do I need other platform backends ? If I remember correctly, this is the rendering engine used by Qt. QWindows looks sufficient to me. And even, do I really need it ? I would expect Qt to have a default rendering engine on Windows and not load it by a plugin, no ?
-
platformthemes : seeing a DLL with a xdg in the name feels quite strange. I feel that this plugin is supposed to read the theme defined in a xdg setup and apply it. But I am not aware of the XDG being implemented under Windows. Is it ?
-
styles/qwindowsvistastyles ? My feeling is that this is an emulation of the Vista style when running under lower versions of Windows (like XP) and that from Vista to Windows 10, I probably won't need it.
What do you think ?
My application works fine if I remove most of this, but will it run fine on anybody's computer ? That's the tricky question.
-
-
Hi and welcome to devnet,
What are you using to build your packaged application ?
-
Thanks for taking the time to answer my question.
I am using PyInstaller on Windows 10. My application itslef uses pyside2, QtWidgets, QtCore and QtGui. No other dependencies identified...
Does it help ?
-
Ok, so not a specialized tool that would inspect more in details what you are currently using from PySide2.
Overall, your analysis looks fine. The platform plugin is mandatory for the platform you are using. Offscreen can be used for example on a headless CI machine. Platform input context can be used whenever you need a special keyboard. This is not limited to mobile devices, kiosk like ATM can use it.
-
I have been looking for documentation on how I could activate other kind of platform from PyQt, without any solution. Do you have any hints ?
I tried to remove all other platforms plugin and my application runs just the same. And some of them like qwebgl pump in several dependencies which are of non negligible size.
ps : for some reason, I don't receive the notifications of the forum, that's why it took me long to answer.
-
Well, if you are building an application for Windows, you won't be able to use that application as is on Linux or macOS. You'll have to repeat the process for the other platforms. Unless you distribute your application through Pypi or conda.
Qt provides several helper applications to help for deployment. You can check the corresponding platform pages in the documentation. Just search for "deployment".
As for the notification, you should check your settings. IIRC, they should be on by default.
-
I got it. But let's find out why it's happening...
The python interpreter and all imported modules are included in the executable file. So it even includes those modules which are not required by your application.
For example includingpandas
library in just aprint("hello world")
program which isn't actually imported will also be included. So it will make your executable file 40MB+ or something.Best Solution: Try setting up your environment with a
virtualenv
, and install only the required libraries.Alternative Solution: You can try adding modules you want to exclude to the excludes list under Analysis in your spec file. For example:
pyinstaller --onefile --exclude matplotlib --exclude scipy --exclude pandas --exclude numpy.py
But it's not practical considering how big the exclusion list would be. In my case, I have 40+ libraries installed so trying this method, naming all 40 files would be just insane!
Better try the other solution which I provided...
-
You misunderstood me. I was referring to the ability to activate other QPA platforms than windows. According to the list of plugins installed in the platforms dir, I have : minimal, webgl, offscreen and windows.
I eventually found the way to activate them : I can specify the
-platform XXX
on the command-line of QApplication and it will switch to the XXX platform abstraction. I tried with minimal, offscreen and webgl. For all these, nothing is displayed and it is impossible to have any user interaction.This confirms my initial impression : for an actual application designed to be used interactively by a user on the Windows OS, the only platform qpa plugin which make sense is qwindows.dll .
I also found out that platformthemes/xdgdesktopportal is designed for usage in flatpak, which does not fit my distribution channel.
So, my initial choices of ditching out all these is correct.
Thanks for your feedback anyway.
Cheers,
Philippe
-
Thanks Abhay. I was also doing more or less what you describe.
Another intersting trick which I noticed : pyinstaller3 will track all dependencies of the Qt plugins it finds in the site-packages/PyQt5/Qt/plugins . By removing the unneeded plugins directly in the virtualenv install, you can save yourself a lot of dependencies.
For example, PyQt5/Qt/plugins/platform/qwebgl.dll will force the inclusion of :
- Qt5WebSockets.dll
- Qt5Network.dll
- WS2_32.dll
- Qt5Quick.dll .
Or PyQt5/Qt/plugins/platformthemes/qflatpak.dll will include Qt5Dbus.
Assuming that like me, you don't actually need any of these plugin, removing them directly in the virtual env directory is the way to go, to avoid having them in your final distribution.
I plan to write a full article on how to reduce the size of a pyinstaller generated executable using all these tricks and a few more.