Search code examples
pythonpyqt4pyqt5pyinstaller

Runtime error when calling a .exe made with PyInstaller including PyQt4


So, I have two .py files, one generated by QtDesigner and another which basically implements the functionality of the GUI. Using, pyinstaller, I generated a .exe file to use it on systems without python and the associated libraries.

The command: pyinstaller my_script.py runs fine without any errors.

The problem occurs when I run the .exe file.

Error:

Qt: Untested Windows version 10.0 detected! Traceback (most recent call last): File "site-packages\PyInstaller\loader\rthooks\pyi_rth_qt4plugins.py", line 41, in ImportError: No module named 'PySide'

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "site-packages\PyInstaller\loader\rthooks\pyi_rth_qt4plugins.py", line 43, in File "", line 2237, in _find_and_load File "", line 2226, in _find_and_load_unlocked File "", line 1191, in _load_unlocked File "", line 1161, in _load_backward_compatible File "C:\python\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 714, in load_module module = loader.load_module(fullname)

RuntimeError: the PyQt4.QtCore and PyQt5.QtCore modules both wrap the QObject class [11364] Failed to execute script pyi_rth_qt4plugins

So I tried to find a solution to this. These are the solutions I tried:

How to force PyQt5 use for QObject class? - simply make the PyQt import as the first statement doesn't resolve the issue.

https://github.com/tzutalin/labelImg/issues/268 - Here it is recommended to remove PyQt4 and use only PyQt5. I do have both of them on my system, some projects rely on PyQt5 and some on PyQt4 hence I don't want remove the latter. Also, there has to be another solution, is making me not do this.

https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000551170-PyQt4-and-PyQt5-collisions-in-PyCharm-2017-2-1-when-debugging-QGIS-application - This was a similar error, so I added: matplotlib.rcParams['backend'] = 'Qt4Agg' matplotlib.rcParams['backend.qt4'] = 'PyQt4'

to my imports, still didn't work.

Note: I am using:

PyCharm 2018.1 (Community Edition)

Build #PC-181.4203.547, built on March 26, 2018

JRE: 1.8.0_152-release-1136-b20 amd64

JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o

Windows 10 10.0

and the code works fine in the IDE.

EDIT:

My imports are:

from PyQt4 import QtCore, QtGui
from matplotlib.backends.backend_qt4agg import FigureCanvasQTagg as Canvas

I am not adding any other import statements related to Qt.

EDIT - 2:

Trying cx_Freeze instead of PyInstaller, here is the setup file.

import sys
from cx_Freeze import setup, Executable

base = None
if sys.platform == "win32":
    base = "Win32GUI"

additional_mods = ['numpy.core._methods', 'numpy.lib.format', 
'numpy._distributor_init']

setup( name="ASCII2fig",
       version = "0.1",
       description = "GUI",
       options = {'build_exe': {'includes': additional_mods}},
       executables = [Executable("ASCII2figALL_main_edited.py", base=base)])

I added the additional_mods after executing the script once following ImportError, which are non-stop. Any ways to hack and find which libraries I should mention explicitly?

Additionally, I also tried to check which libraries are actually being imported when I run my main script with Qt using:

from modulefinder import ModuleFinder

filename = "ASCII2figALL_main_edited.py"
finder = ModuleFinder()
finder.run_script(filename)
for name, mod in finder.modules.items():
    print(name)

and apparently, it is importing PyQt5 internally. As mentioned before, I have NO import statements mentioning PyQt5.

Edit - 3

So, I changed the code to pure PyQt5, updated the pyinstaller to the latest version - 3.4, and now there is a new issue where it doesn't find the Qt plugins. It is still somehow importing PyQt4 and I don't know where.


Solution

  • So, I finally made it to work. Not the ideal case, where I don't have to change the library to PyQt5 and make sure everything is in order with PyInstaller, but it works. So here is what I did:

    1. Installed Python version 3.5 - This was because after I updated to the latest PyInstaller version (3.4) and tried to run on python 3.4, I was getting a new error where it was not able to find Qt plugins. After some searching, I figured that since I installed PyQt5 on Python version (3.4) using a .whl file I found on Python Extension Packages for Windows, the installation didn't come bundled with sip. Additionally, when I tried to install PyQt5 on Python 3.4 using pip, it wouldn't install.

    2. Installed PyQt5 and all other libraries on the new Python version using pip. Note: This version of python doesn't have a PyQt4 installed, so it is quite possible that this was the reason. I will install PyQt4 on this python version and try making the .exe again using PyInstaller and see what happens.

    So, to summarize, PyQt5 + Pyinstaller works only for Python version >= 3.5. Hope it helps others!