PyInstaller; "could not find or load the Qt platform plugin "windows"
Asked Answered
E

6

10

My PyInstaller spec:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['test.py'],
             pathex=['C:\\Users\\admin\\compile'],
             binaries=[('C:\\Python361\\Lib\\site-packages\\PyQt5\\Qt\\plugins\\platforms\\qwindows.dll', 'qwindows.dll')],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)

pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='test',
          debug=False,
          strip=False,
          upx=False,
          runtime_tmpdir=None,
          console=False , icon='icon.ico')

So I have ran into the problem where I will compile my PyQt5 5.8.2 (with Python 3.6.1) program with the latest version of PyInstaller from pip, and it works! The statically linked, onefile executable works on my computer with all the Qt stuff on it.

But then I test it on any computer or virtual machine that doesn't have the Qt environment set up already, and it crashes on start because of the "could not find or load the Qt platform plugin 'windows'" error. If you look at the spec you'll notice that I attempted to store the DLL in the binary list manually so PyInstaller would store it in the executable, but that didn't work.

I would like to know what I need to change so that I can compile my application without having to do something like include the platforms folder in the folder with the executable (I want everything to be in the executable), would it be as simple as a change in the spec file that I didn't realize so that it stores the DLL in the executable?

By the way, this is not a duplicate. I looked at some of the other questions and all of them were either for a different type of application or the solution was to downgrade or store the DLL in the folder and I can't do either of those.

EDIT: So I changed it to onedir just to see if it was even in there, and qwindows.dll is inside of the folder. There is also a qt5_plugins folder which has a platforms folder which also has a qwindows.dll. So how is it not detecting the dll??

Edmead answered 24/11, 2017 at 7:56 Comment(4)
You can try adding the path to those libraries in the pathex variableTayib
Just tried that by changing to pathex=['C:\\Users\\admin\\compile', 'C:\\Python361\\Lib\\site-packages\\PyQt5\\Qt\\plugins\\platforms'], didn't change anythingEdmead
Also @Tayib I am doing this from a clean virtual machine if that mattersEdmead
I edited the question since I found an important detail.Edmead
H
8

There seem to be two solutions, the first one worked fine for me:

  • copy platform directory to directory of your executable. You'll find the platform directory at a location like c:\Users\<username>\envs\<environmentname>\Library\plugins\platforms or

  • Upgrade to a newer version of pyqt: conda install -c anaconda pyqt

Use the second option with care: Do not try to use pip for pyqt installation if you have a conda environment, this might break your conda installation: https://github.com/ContinuumIO/anaconda-issues/issues/1970

Heldentenor answered 20/5, 2018 at 4:57 Comment(0)
F
3

I had an issue where my python code worked fine, but the compiled .exe file would provide the "could not find or load the Qt platform plugin windows" problem. I fixed the problem by copying the ~PyQt5\Qt\plugins\platforms folder from the program's directory, generated by using pyinstaller --onedir main.py, to the folder holding the .exe file.

It seems that in my case the only way "helping" my program detect the required .dlls was having the platforms folder next to the main.exe. Pasting the platforms folder to the program's directory after using pyinstaller --onefile main.py also makes the program work.

Fathometer answered 12/1, 2019 at 11:46 Comment(1)
It worked for me. I have an "app" compiled with pyinstaller that involves matplotlib and seaborn graphics. The executable works but gives the error when the plots pop up. Running the python scrips within Pycharm works correctly. I copied the folder platforms located, in my case, in C:\Anaconda3\Lib\site-packages\PyQt5\Qt\plugins --> problem solvedPragmatic
N
1

I just update my pyqt5 package to 5.10.1 and fix that.

Nannie answered 5/3, 2018 at 19:12 Comment(1)
comment qualityImmesh
F
1

Got the same problem with PyQt6 6.0.3 and PyInstaller 4.3.

First a tried a one-folder bundle which worked fine after adding the platform and style plugins to the binaries list and PyQt6.sip to the hiddenimports one (The latter may be need only if using PyQt6).

When i tried the one-file bundle i got the platform plugin error. First i checked if the files are being copied by looking in the temp folder where the bundle is unpacked during runtime (with the error dialog open) and all the DLL's were there. When i copied then to the same folder as the executable it worked fine, the problem was Qt wasn't finding them in the temp folder.

I found the solution reading about QT_PLUGIN_PATH in the Qt documentation then looking in this PyInstaller commit.

After adding the plugins' DLLs just add a runtime hook to set QT_PLUGIN_PATH.

Also if using UPX the plugins' DLLs need to be added to the upx_exclude list.

Here's the hook and spec file i used, with default options removed:

pyQtHook.py

import os
import sys
from pathlib import Path

os.environ['QT_PLUGIN_PATH'] = str( Path( sys._MEIPASS ) / 'PyQt6/Qt6' )

oneFile.spec

from pathlib import Path

root = Path.cwd()
qtRoot = root / 'env/Lib/site-packages/PyQt6/Qt6'

analysis = Analysis(
    scripts = [
        root / 'src/main.py',
    ],
    pathex = [
        root,
        qtRoot / 'bin',
    ],
    binaries = [
        ( qtRoot / 'plugins/platforms/qwindows.dll', 'PyQt6/Qt6/plugins/platforms' ),
        ( qtRoot / 'plugins/styles/qwindowsvistastyle.dll', 'PyQt6/Qt6/plugins/styles' ),
    ],
    hiddenimports =[
        'PyQt6.sip',
    ],
    runtime_hooks = [
        'pyQtHook.py',
    ],
)

pyz = PYZ( analysis.pure, analysis.zipped_data )

exe = EXE(
    pyz,
    analysis.scripts,
    analysis.binaries,
    analysis.zipfiles,
    analysis.datas,
    name = 'MyApp',
    console = False,
    upx = True,
    upx_exclude = [
        'qwindows.dll',
        'qwindowsvistastyle.dll',
    ],
)
Foxy answered 28/4, 2021 at 10:21 Comment(1)
I'am trying the same as you did like for hours. No way... Still the same error... :-/Evangelize
L
0

This is an old question but I have been looking for a solution to this issue for days now and I finally managed to fix it WITHOUT having to manually copy the folder. Since this question also uses the .spec file I thought this would be the right place. The idea is that the .exe is looking for the .dlls in the path ./platforms/*.dll so I simply added all of the dlls to the binaries array in the spec file, where their path within the bundle is platforms/*.dll. This is because binaries is an array of tuples where the first value is the path to the file and the second one is the path within the bundle (so pretty much the path inside the .exe "container").

Besides that, the top states mode: python which I assume means it is executed as a python script, therefore it should support variables, strings and concatenation. So my spec file ended up looking something like this:

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

pf_foldr='C:\\Users\\Gabryxx7\\anaconda3\\envs\\<env_name>\\Library\\plugins\\platforms\\'

a = Analysis(['C:\\Users\\Gabryxx7\\PycharmProjects\\<proj_name>\\program.py'],
             pathex=['C:\\Users\\Gabryxx7\\PycharmProjects\\<proj_name>\\'],
             binaries=[(pf_foldr+'qwindows.dll', 'platforms\\qwindows.dll'),
             (pf_foldr+'qdirect2d.dll', 'platforms\\qdirect.dll'),
             (pf_foldr+'qoffscreen.dll', 'platforms\\qoffscreen.dll'),
             (pf_foldr+'qwebgl.dll', 'platforms\\qwebgl.dll')
             ],
             datas=[],
             hiddenimports=['GUI', 'API', 'Threading', 'ssl', 'pyodbc'],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='programName',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True ) # False to avoid the console

I had previously tried every solution I found online: setting up the environmental variable QT_QPA_PLATFORM_PLUGIN_PATH, reinstalling Anaconda, updating all the packages, tried with PyPi version and no venvs, but nothing worked. In the end copying the platforms folder with the dlls did the trick and so did the spec file editing to avoid the manual step.

Lyns answered 27/7, 2020 at 12:29 Comment(1)
this appears to not be working when using winx64, python 3.7.x, venv + pyside6.Murphey
P
0

After almost explode my brain trying to solve this problem I figure out a solution that worked for me.

inside the SPEC file I added the clause: upx_exclude=['qwindows.dll'],

Turns out this DLL is corrupted when compressed during the freezing process by PyInstaller. Adding the DLL to the upx_exclude clause prevent this problem of occuring.

You can check part of my SPEC file here:

...

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='Hydro Tax Automation App',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=['qwindows.dll'],
          runtime_tmpdir=None,
          console=False)
Polydactyl answered 12/3, 2021 at 2:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.