py2app icon indicating copy to clipboard operation
py2app copied to clipboard

bundled PyQt5 apps fail to start since py2app v0.26

Open MAKOMO opened this issue 4 years ago • 10 comments

Using python 3.9.7 installed from python.org on macOS 11.6, the trivial PyQt5 GUI app

from PyQt5.QtWidgets import QApplication, QWidget

app = QApplication([])
window = QWidget()
window.show()
app.exec()

fails to run after bundling with

from setuptools import setup

OPTIONS = {
    'strip': False,
    'argv_emulation': False
}

setup(
    app = ['main.py'],
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
    script_args = ['py2app']
)

## build with:
# sudo python3 setup.py build

on py2app v0.26 and v0.26.1 installed via pip as well as using the current py2app trunk, but runs fine if build with v0.25 or older.

[Max:/Users/luther/Desktop/tmp/Test2] dist/main.app/Contents/MacOS/main 
qt.qpa.plugin: Could not load the Qt platform plugin "cocoa" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: cocoa, minimal, offscreen, webgl.

Abort trap: 6

Reason seems to be the extra Qt plugins folder on top of the Content folder that is created since py2app v0.26. After removing this one starts fine.

# sudo rm -rf dist/main.app/Contents/plugins
# dist/main.app/Contents/MacOS/main 

Is there a reason to duplicate those Qt plugins on the top level while they are already available under Resources?

Resources/lib/python3.9/PyQt5/Qt5/plugins

MAKOMO avatar Oct 11 '21 07:10 MAKOMO

Sigh. I'll have to debug. The changes I made in 0.26 were necessary to get working apps on my machine.

How was PyQt installed on your machine, through PyPI or through a system like homebrew?

ronaldoussoren avatar Oct 11 '21 12:10 ronaldoussoren

Sorry for the troubles. Installation was standard python.org Python installation and packages all installed via PyPI directly without any virtual environment. To me the issue seems to be those extra plugins that get installed on the toplevel of the app which seem to be preferred by Qt (default plugin location) over those installed deeper in the PyQt5 directory in a subdirectory of Resources. py2app versions before this seem not to have created that toplevel plugins directory at all.

MAKOMO avatar Oct 11 '21 12:10 MAKOMO

Oh, should have noted that I am using the current PyQt5 package which is 5.15.4 at the moment.

MAKOMO avatar Oct 11 '21 12:10 MAKOMO

The sigh was not directed at you.

I'll have to look at the source code to be sure, but wouldn't be surprised if this issue is caused by code that I added to deal with PyQt from homebrew where additional files have to be copied into the app because Qt isn't in the PyQt directory.

ronaldoussoren avatar Oct 11 '21 13:10 ronaldoussoren

I see the same issue, but I can narrow it down to commit c9fcb5e41da33a5ce8a60c71b438506d33ce9451. The previous commit does not produce the error, and commit d206e57f14b3a31cbd43dcdcaa745b92d5286b29 does not resolve the issue (though I don't think it was intended to resolve it).

I have PyQt5 installed via PyPi in a pyenv virtual environment (via Homebrew).

mrclary avatar Oct 28 '21 22:10 mrclary

FWIW, on my installation, PyQt5 = 5.12.3 os.path.dirname(PyQt5.__file__) = '/Users/rclary/.pyenv/versions/3.9.5/envs/spy-build-py2app/lib/python3.9/site-packages/PyQt5' QLibraryInfo.location(QLibraryInfo.LibrariesPath) = '/Users/rclary/.pyenv/versions/3.9.5/envs/spy-build-py2app/lib/python3.9/site-packages/PyQt5/Qt/lib'.

Under what condition do you expect os.path.dirname(PyQt5.__file__) and QLibraryInfo.location(QLibraryInfo.LibrariesPath) to be the same? Or different?

mrclary avatar Oct 29 '21 13:10 mrclary

Would it work to use

if os.path.dirname(PyQt5.__file__) not in qtdir:

instead of

if qtdir != os.path.dirname(PyQt5.__file__):

?

mrclary avatar Oct 29 '21 15:10 mrclary

It seems to me that if PyQt is added to the 'packages' directive, everything in the package should be included in the build because it will be outside the zip folder. Then, the only question is whether the library is located somewhere inside the package directory or somewhere else. Only if it is located somewhere outside the package directory should the plugin directory be copied to Resources.

Perhaps an even better solution would be

if not qtdir.startswith(os.path.dirname(PyQt5.__file__)):

mrclary avatar Oct 29 '21 16:10 mrclary

@ronaldoussoren, has there been any progress on this?

mrclary avatar Jan 20 '22 16:01 mrclary

This appears to be fixed in 0.28.5 with py3.9.9 from python.org, and either PyQt 5.15.6 or 6.4.0 from PyPI.

mharbison72 avatar Jan 25 '23 22:01 mharbison72