Windows 10, Python 3.5, PyQt5 is installed via Pip, pyinstaller 3.2.1 also installed via Pip. I can make a little PyQt5 qml app that works fine when run normally under Python.
If I have a Python module called test.py that contains:
from PyQt5.QtWidgets import QApplication
from PyQt5.QtQuick import QQuickView
and do:
pyinstaller main.py
I get:
3452 ERROR: Could not find qmake version 5.x, make sure PATH is set correctly or try setting QT5DIR.
3452 ERROR: Cannot find QT_INSTALL_QML directory, "qmake -query QT_INSTALL_QML" returned nothing
followed by:
Traceback (most recent call last):
File "C:\Python35\Scripts\pyinstaller-script.py", line 11, in <module>
load_entry_point('PyInstaller==3.2.1', 'console_scripts', 'pyinstaller')()
File "c:\python35\lib\site-packages\PyInstaller\__main__.py", line 90, in run
run_build(pyi_config, spec_file, **vars(args))
File "c:\python35\lib\site-packages\PyInstaller\__main__.py", line 46, in run_build
PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
File "c:\python35\lib\site-packages\PyInstaller\building\build_main.py", line 788, in main
build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build'))
File "c:\python35\lib\site-packages\PyInstaller\building\build_main.py", line 734, in build
exec(text, spec_namespace)
File "<string>", line 16, in <module>
File "c:\python35\lib\site-packages\PyInstaller\building\build_main.py", line 212, in __init__
self.__postinit__()
File "c:\python35\lib\site-packages\PyInstaller\building\datastruct.py", line 161, in __postinit__
self.assemble()
File "c:\python35\lib\site-packages\PyInstaller\building\build_main.py", line 470, in assemble
module_hook.post_graph()
File "c:\python35\lib\site-packages\PyInstaller\building\imphook.py", line 409, in post_graph
self._load_hook_module()
File "c:\python35\lib\site-packages\PyInstaller\building\imphook.py", line 390, in _load_hook_module
attr_value = sanitizer_func(attr_value)
File "c:\python35\lib\site-packages\PyInstaller\building\utils.py", line 466, in format_binaries_and_datas
src_root_path_or_glob))
FileNotFoundError: Path or glob "Qt" not found or matches no files.
If I comment out the second line from test.py (the one about QtQuick) PyInstaller succeeds.
I can't make the path point to qmake because I don't have qmake on my machine. I don't really understand why I need qmake?
With Python 3.4.4 and PyQt5 5.5.1 (from https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.5.1/ - I think this is the last PyQt5 for 3.4) and PyInstaller 3.2.1 this all works fine out of the box.
The difference I think is that the PyQt5 directory structure under Lib\site-packages\PyQt5
is very different between 3.4 and 3.5 and I guess PyInstaller isn't coping with that yet. In particular, Python34 has the Qt5 binaries (Qt5Core.dll etc) in the root of Lib\site-packages\PyQt5
whereas in Python35 they end up tucked away under Lib\site-packages\PyQt5\Qt\bin
. There are a lot of other differences too.
Anyway, the easy answer is therefore use Python34 / PyQt5.5.1. FWIW I have sort of got it working with Python35 and latest PyQt5 (5.8.1), but it's a bodge. I have both Python34 and Python35 installed, and the following (in this order) in my Windows path:
C:\Python35\
C:\Python35\Scripts\
C:\Python35\Lib\site-packages\PyQt5\Qt\bin
C:\Python34\Lib\site-packages\PyQt5
The Python34 line has to be there otherwise we get the Could not find qmake version 5.x
stuff, and the Python35\Lib\site-packages\PyQt5\Qt\bin
path being above that seems to make it pick up the correct binaries.
Doing this, pyinstaller reports success, but when I run I get a failure about Cannot load library ... dist\main\qml\QtQuick\Controls\qtquickcontrolsplugin.dll: The specified procedure could not be found
. This can be solved by manually copying over Python35\Lib\site-packages\PyQt5\Qt\qml\QtQuick\Controls\qtquickcontrolsplugin.dll
to dist\main\qml\QtQuick\Controls
. After that my app runs as expected.
I haven't found a way to make pyinstaller pick up the correct qtquickcontrolsplugin.dll automatically.
I guess leaving C:\Python34\Lib\site-packages\PyQt5
in the path it's probably picking up some other wrong files from Python34, and if that's the case you can copy them over manually or try to fiddle with paths etc. to try to make the right thing happen, but I'm just going to use Python34 until PyInstaller gets fixed.