Skip to content

Make PyQt5.sip available as sip at runtime#1267

Merged
htgoebel merged 1 commit intopyinstaller:developfrom
tjstum:reintegrate
Jul 27, 2015
Merged

Make PyQt5.sip available as sip at runtime#1267
htgoebel merged 1 commit intopyinstaller:developfrom
tjstum:reintegrate

Conversation

@tjstum
Copy link

@tjstum tjstum commented May 12, 2015

This fixes an issue where, at least on Windows, trying to use a PyQt5 module results in an ImportError at runtime.

Without this patch, a module using python-qt5 exits with the following error:

Traceback (most recent call last):
  File "<string>", line 36, in <module>
  File "C:\Python27\Lib\site-packages\PyInstaller\loader\pyi_importers.py", line
 420, in load_module
    fp = open(filename, 'rb')
ImportError: No module named sip
LOADER: RC: -1 from pyi_rth_qt5plugins

When I looked at the built binary, it looks like the module is just getting named PyQt5.sip. The python-qt5 package expects the name sip. This small patch is sufficient to fix the problem, but if you would prefer a different approach, please let me know.

@htgoebel htgoebel added the version:develop Related to the current development branch label May 19, 2015
@htgoebel
Copy link
Member

Hmm, I'm wondering why this did not occur earlier. And in hook-PyQt5.py there is a hidden import for sip. Can you please check this with the newest development head? Thanks.

@htgoebel htgoebel added the state:need info Need more information for solve or help. label May 19, 2015
@tallforasmurf
Copy link
Contributor

I can report the "no module named sip" happened for me also, on Windows only, using the Python3 branch as of a week ago. I did not investigate the cause. I circumvented the problem by adding hidden-import=sip to the command line.

@tjstum
Copy link
Author

tjstum commented May 21, 2015

This is indeed still happening.

I installed PyInstaller at 6f84a5a, and I tried this example code:

import sys
from PyQt5 import QtWidgets

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    QtWidgets.QMessageBox.information(None, "Hello World", "Hi there!")

I built it with PyInstaller by just running pyinstaller <source_file> with no other arguments. Running the built binary gives:

Traceback (most recent call last):
  File "<string>", line 36, in <module>
  File "c:\python27\lib\site-packages\PyInstaller-2.1.1dev_6f84a5a-py2.7.egg\PyI
nstaller\loader\pyi_importers.py", line 420, in load_module
    module = imp.load_module(fullname, fp, filename, self._c_ext_tuple)
ImportError: No module named sip

If I apply this one commit (cherry-picked on top) and rebuild the exact same code, the exact same way, the test works correctly (I get a message box saying "Hello")

This is on Windows 7 x64 with Python 2.7 (also 64 bit). PyQt5 is installed from the python-qt5 package version 0.1.8 (the current in PyPI)

@htgoebel
Copy link
Member

I'm hesitating merging this because it hacks sys.modules, which looks dangerous to me. What makes me wonder is:

I circumvented the problem by adding hidden-import=sip to the command line.

But sip already is listed as hidden import in hook-PyQt5.py.

And I just installed PyQt5-5.4.1-gpl-Py3.4-Qt5.4.1-x64.exe in a wine-machine. There is no module PyQT5.sip in C:\Python34\lib\site-packages.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should first test if sip can be imported:

try:
  import sip
except ImportError:
  try:
    ... your code ... 

It would be even better if we'd verify the module name.

@tallforasmurf
Copy link
Contributor

I circumvented the problem by adding hidden-import=sip to the command line.

But sip already is listed as hidden import in hook-PyQt5.py.

Exactly so, and also in every (I think?) other PyQt5 hook, which made it very curious indeed.

@codewarrior0
Copy link
Contributor

The sip folder inside the PyQt5 package is not a subpackage, but ModuleFinder is detecting it as a NamespacePackage. Removing the sip folder from PyQt5 results in a working binary, and it correctly finds the sip module that is directly inside site-packages.

@codewarrior0
Copy link
Contributor

From the modulegraph documentation:

level – The import level. The value should be -1 for classical Python 2 imports, 0 for absolute imports and a positive number for relative imports ( where the value is the number of leading dots in the imported name).

level=-1 is the default import level and it is implicitly used when loading the hidden import modules in build.py:718:

hiddenmod = self.graph.import_hook(item, from_node)

It makes sense that -1 should not ever be used when building for python3. Although, I'm curious if this issue occurs on python2. But I don't think that's the real issue.

A good question is why the folder PyQt5/sipis being detected as a NamespacePackage - it isn't specified as a ns-package by the setuptools .pth files and shouldn't be detected as such.

@tjstum
Copy link
Author

tjstum commented May 29, 2015

So this is a modulegraph bug, then?

I am happy to do the suggestion in #1267 (comment) (i.e. trying to see if sip is normally available and then patching sys.modules as a last resort). I do think, though, that there should be some workaround (unless there's some way to avoid the issue altogether).

Based on what I have seen, I don't think this has anything to do with Python 2 vs Python 3. I first encountered this issue on Python 2.7, but it also sounds like people are encountering the same problem in Python 3. I could be mistaken, though.

@htgoebel: would you like me to make the change you suggested and update my branch?

@htgoebel
Copy link
Member

htgoebel commented Jun 1, 2015

@htgoebel: would you like me to make the change you suggested and update my branch?

Yes.

(I would prefer, if this would be fixed in modulegraph, though.)

@tjstum
Copy link
Author

tjstum commented Jul 27, 2015

Sorry for the delay here. I modified my commit as you suggested, and I updated it to the current base.

@htgoebel htgoebel removed the state:need info Need more information for solve or help. label Jul 27, 2015
@htgoebel htgoebel self-assigned this Jul 27, 2015
htgoebel added a commit that referenced this pull request Jul 27, 2015
Make PyQt5.sip available as sip at runtime
@htgoebel htgoebel merged commit 13c19d5 into pyinstaller:develop Jul 27, 2015
@htgoebel
Copy link
Member

Thanks.

@matysek matysek added this to the PyInstaller 3.0 milestone Oct 3, 2015
@tjstum tjstum deleted the reintegrate branch November 11, 2015 22:34
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

version:develop Related to the current development branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants