takluyver / pynsist

Build Windows installers for Python applications
https://pynsist.readthedocs.io/
Other
882 stars 119 forks source link

The pyqt5 example is not working for the latest versions of Python and PyQt5 #225

Closed rodrigomologni closed 3 years ago

rodrigomologni commented 3 years ago

Hi, team!

I updated the installer.cfg file of the pyqt5 example to run on current versions of Python and PyQt5:

installer.cfg ``` [Application] name=List App (PyQt5) version=1.0 entry_point=listapp:main [Python] version=3.8.8 bitness=64 format=bundled [Include] packages=listapp pypi_wheels= PyQt5==5.15.4 PyQt5-Qt5==5.15.2 PyQt5-sip==12.8.1 ```

The pyqt5 example is working until Python 3.7.9 and PyQt5 5.15.2.

installer.cfg ``` [Application] name=List App (PyQt5) version=1.0 entry_point=listapp:main [Python] version=3.8.8 bitness=64 format=bundled [Include] packages=listapp pypi_wheels= PyQt5==5.15.2 PyQt5-sip==12.8.1 ```
Traceback (most recent call last):
  File "build\nsis\List_App_(PyQt5).launch.pyw", line 34, in <module>
    from listapp import main
  File "build\nsis\pkgs\listapp\__init__.py", line 2, in <module>
    from PyQt5 import QtWidgets
  File "build\nsis\pkgs\PyQt5\__init__.py", line 49, in <module>
    find_qt()
  File "build\nsis\pkgs\PyQt5\__init__.py", line 44, in find_qt
    os.add_dll_directory(dll_dir)
  File "os.py", line 1105, in add_dll_directory
OSError: [WinError 87] The parameter is incorrect: 'build\\nsis\\pkgs\\PyQt5\\Qt\\bin'
installer.cfg ``` [Application] name=List App (PyQt5) version=1.0 entry_point=listapp:main [Python] version=3.7.9 bitness=64 format=bundled [Include] packages=listapp pypi_wheels= PyQt5==5.15.4 PyQt5-Qt5==5.15.2 PyQt5-sip==12.8.1 ```
Traceback (most recent call last):
  File "build\nsis\List_App_(PyQt5).launch.pyw", line 34, in <module>
    from listapp import main
  File "build\nsis\pkgs\listapp\__init__.py", line 2, in <module>
    from PyQt5 import QtWidgets
ImportError: DLL load failed: The specified module could not be found.

Does anyone know how to solve this problem, please?

takluyver commented 3 years ago

Are you running it from the build directory? The paths in the tracebacks look like that - if so, does it work when you install it?

For the first error, I might guess that os.add_dll_directory() expects an absolute path rather than a relative one. If so, it looks like PyQt5 is assuming that __file__ gives an absolute path, which is not necessarily true (though it normally is, and we could probably make it more true in code installed by Pynsist).

The add_dll_directory function is new in Python 3.8, and PyQt5 just skips calling it if it's not there. Unless there's some fallback mechanism implemented elsewhere for older versions of Python, that implies that in at least some situations, it won't work with Python < 3.8. If it always worked without add_dll_directory, they wouldn't use it. :confused:

rodrigomologni commented 3 years ago

Hi, @takluyver! Thank you for answering me.

Are you running it from the build directory? The paths in the tracebacks look like that - if so, does it work when you install it?

Yes, I'm running the launch from the build directory, using the embed Python. The same error occurs if the installed Python is used. However, the example is works. I can run it from the entry-point using either the embed or installed Python.

image

For the first error, I might guess that os.add_dll_directory() expects an absolute path rather than a relative one. If so, it looks like PyQt5 is assuming that file gives an absolute path, which is not necessarily true (though it normally is, and we could probably make it more true in code installed by Pynsist).

Yes, you're right. OSError is overcome when the absolute path is used.

43        try:
44            dll_dir = os.path.abspath(dll_dir)  # changed
45            os.add_dll_directory(dll_dir)
46        except AttributeError:
47            pass
Traceback (most recent call last):
  File ".\List_App_(PyQt5).launch.pyw", line 34, in <module>
    from listapp import main
  File ".\pkgs\listapp\__init__.py", line 2, in <module>
    from PyQt5 import QtWidgets
ImportError: DLL load failed while importing QtWidgets: The parameter is incorrect.

Observation: The Qt installation files have been moved to the PyQt5-Qt5 package since PyQt5 version 5.12.3. The import error occurs since this version.

takluyver commented 3 years ago

OK, I think the absolute path issue can be fixed relatively easily - see #221.

BTW, there's no guarantee that running from the build directory works in general. It probably often does with the current way Pynsist works, but the process of creating the installer from those files and installing them somewhere is 'allowed' to make changes which may be necessary for the application to run. :slightly_smiling_face:

rodrigomologni commented 3 years ago

I would like to use Pynsist to distribuite my app for testing. However, unfortunately, I cannot overcome this problem. :disappointed_relieved:

Thanks for your attention! :v:

takluyver commented 3 years ago

I think #226 should fix it for Python 3.8+.

I'm not sure there's anything I can do for older Python versions that don't have the add_dll_directory function that PyQt5 seems to rely on. You may need to stick to an older version of PyQt5 for those Pythons.

rodrigomologni commented 3 years ago

Hi, @takluyver! I performed the following comparison:

Python PyQt5 PyQt5-Qt5 PyQt5-sip pynsist 2.6 pynsist 2.7dev
3.7.9 5.15.2 - 12.8.1 :heavy_check_mark: :heavy_check_mark:
3.7.9 5.15.3 5.15.2 12.8.1 :x: :x:
3.7.9 5.15.4 5.15.2 12.8.1 :heavy_check_mark: :heavy_check_mark:
3.8.8 5.15.2 - 12.8.1 :x: :heavy_check_mark:
3.8.8 5.15.3 5.15.2 12.8.1 :x: :x:
3.8.8 5.15.4 5.15.2 12.8.1 :x: :heavy_check_mark:

You solved the problem! Thank you! 🎉

P.S.: In my first test, the pyqt example was not working with Python 3.7.9 and PyQt5 5.15.4. :man_shrugging:

takluyver commented 3 years ago

Thanks, that's very thorough! It looks like PyQt5 5.15.3 might simply have had a minor bug in it that was fixed in 5.15.4 (there's a message in the changelog saying "Fixed the Qt subdirectory in __init__.py.").

I want to get #219 fixed as well, then I'll make a new release.

sander76 commented 3 years ago

Many thanks for the absolute path fix. It solves installation issues with wxpython too !!