Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue when running pyinstaller generated .exe #332

Open
tobkum opened this issue Jan 2, 2020 · 8 comments
Open

Issue when running pyinstaller generated .exe #332

tobkum opened this issue Jan 2, 2020 · 8 comments

Comments

@tobkum
Copy link
Contributor

tobkum commented Jan 2, 2020

I'm having an issue with Qt.py in conjunction with pyinstaller. When trying to run the frozen .exe, I get an "ImportError: cannot import name 'QtWidgets' from 'Qt' (E:\xxxx\Qt.pyc)" - (xxxx replacing the path). That pyc file mentioned in the error doesn't exist.
Do I have to use hidden imports when freezing an application with Qt.py or what seems to be the issue here?
Thanks!

@mottosso
Copy link
Owner

mottosso commented Jan 2, 2020

That's an interesting problem. Can you confirm it has access to a binding? E.g. your program should be able to call import PyQt5 or PySide etc. depending on which one you use.

It was a while since I worked with pyinstaller, so I'm not sure what hidden imports do. But at the end of the day, Qt.py is importing a binding like PyQt5 and creating its inner namespaces - such as QtWidgets - from that.

If what you use/bundle is PySide2, then you may perhaps be so bold as to simply say Qt = PySide2 after having imported it, as Qt.py follows the same API, with the only exception being the added QtCompat submodule.

@tobkum
Copy link
Contributor Author

tobkum commented Jan 2, 2020

Some more info - I'd like to write a desktop application, using PySide2 under the LGPL terms, which means (among other things) I have to give the user the ability to replace the bundled PySide2 version with his/her own. I was looking into Qt.py for that reason, so my own code doesn't even mention a specific PySide version, and let Qt.Py handle that part. This works fine when running from a .py file, but somehow breaks when freezing the application via pyinstaller.
Since you're saying it's been a while since you used pyinstaller, you don't happen to know a way to distribute a frozen application that uses Qt.py and - at runtime - imports the vendored Pyside2, or if the user provides his own PySide2 version, imports that one instead?

I'll try the Qt = PySide2 suggestion as soon as I get back home.

@mottosso
Copy link
Owner

mottosso commented Jan 2, 2020

This works fine when running from a .py file, but somehow breaks when freezing the application via pyinstaller.

From what I understand, this is by design. The freezing process is meant to remove any dependency on the source system, the Python distribution and any libraries. As far as I understand, your frozen application isn't exposed to the same sys.path or PYTHONPATH as the original Python application.

But I would be surprised if you couldn't circumvent this; e.g. if the user installed PySide2 at c:\SomeDir\PySide2, then you should be able to - from within your application - say sys.path.insert(0, r"c:\SomeDir") followed by import PySide2.

If so, then you should also find that from Qt import QtWidgets should work too, since that's effectively what it's doing under the hood.

@tobkum
Copy link
Contributor Author

tobkum commented Jan 2, 2020

Hah, good point you got there. I'll check that asap and report back. Cheers!

@aspartamed
Copy link

I am having a similar issue getting Qt.py to work with pyinstaller, I wrote up a simple helloworld example and am trying to get answers on stackoverflow below, I would appreciate any help in understnading how to generate an exe with pyinstaller. My tests show if I just replace Wt with Pyside2 then I can build the exe but I dont want to have to modify my source to build a distribution. https://stackoverflow.com/questions/60977939/pyinstaller-creating-a-standalone-executable-that-uses-qt-py/60979774#60979774

@cmcpasserby
Copy link

cmcpasserby commented Feb 10, 2021

You just have to add PySide2 modules as hidden imports in the PyInstaller spec file then its all fine. In my spec file i just set hiddenimports to be
hiddenimports=["PySide2.QtWidgets", "PySide2.QtGui", "PySide2.QtCore", "PySide2.QtOpenGL"]
if you only add PySide2 it wont work since its just a package not a module, and it does not support wildcards so cant use
PySide2.*

@cmcpasserby
Copy link

It might be possible to avoid this problem by adding PyInstaller Hooks to this package. If there is interests I could look at making a PR for it.

@csmotion
Copy link

Howdy @cmcpasserby and @tobkum. I'm also interested in using Qt.py with PyInstaller to satisfy the PySide2 LGPL terms.
What is the current process for using Qt.py to import a vendored QT binding at runtime? I saw the hook below, but I'm a little unclear on usage.

https://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/utils/hooks/qt.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants