Using cx_freeze with PyQT5 and Python 3 on MacOSX

2019-07-05 12:34发布

问题:

I'm trying to use cx_freeze 4.3.3 on a MacOS running 10.9.2 on a very simple PyQt5 script with Python 3.3.

No errors are returned and the .app is output. However when running the .app from terminal I obtain the error:

LSOpenURLsWithRole() failed with error -10810

which according to Apple's documentation is "Unknown Error".

The very simple code I try to run (PyQt5app.py) is:

import sys
from PyQt5.QtWidgets import QApplication, QDialog

app = QApplication(sys.argv)
form = QDialog()
form.show()
app.exec_()

The file setup.py is:

import sys
from cx_Freeze import setup, Executable

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

options = {
    'build_exe': {
        'excludes': ['Tkinter']  # Sometimes a little finetuning is needed
    }
}

executables = [
    Executable('PyQt5app.py', base=base)
]

setup(name='PyQt5app',
      version='0.1',
      description='Sample PyQt5 GUI',
      executables=executables,
      options=options
      )

and when running I call:

sudo python cx_freeze bdist_mac

obtaining this log : http://pastebin.com/VBxyyBRn

with app returning error above.

So, reading around I see it might be a problem related to including qt files in the app (or at least this was the issue on PyQt4) so I try specifying the qt-menu-nib directory:

sudo python setup.py bdist_mac --qt-menu-nib=/Users/franco/Qt5.2.1/5.2.1/clang_64/plugins/platforms/

obtaining this log: http://pastebin.com/TpRdrSmT

and the same not working error.

If I run the app from PyQt5app.app/Contents/MacOS/PyQt5app I get a lot of bootstrap errors:

Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/site-packages/cx_Freeze-4.3.3-py3.3-macosx-10.9-x86_64.egg/cx_Freeze/initscripts/Console.py", line 27, in <module>
    exec(code, m.__dict__)
  File "PyQt5app.py", line 5, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 1565, in _find_and_load
    return _find_and_load_unlocked(name, import_)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 1532, in _find_and_load_unlocked
    loader.load_module(name)
  File "ExtensionLoader_PyQt5_QtWidgets.py", line 22, in <module>
  File "ExtensionLoader_PyQt5_QtWidgets.py", line 14, in __bootstrap__
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 1565, in _find_and_load
    return _find_and_load_unlocked(name, import_)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 1532, in _find_and_load_unlocked
    loader.load_module(name)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 584, in _check_name_wrapper
    return method(self, name, *args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 495, in set_package_wrapper
    module = fxn(*args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 508, in set_loader_wrapper
    module = fxn(self, *args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 1132, in load_module
    fullname, self.path)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/importlib/_bootstrap.py", line 313, in _call_with_frames_removed
    return f(*args, **kwds)
SystemError: initialization of sip raised unreported exception

Needless to say the script works fine when launching from terminal:

python PyQt5app.py

I most certainly am doing something wrong, so please, can anybody help me?

回答1:

So, after long fighting here is the issue: libzmq . I installed libzmq and specified the --qt-menu-nib option and the simple example above runs in both:

sudo python setup.py build

and

sudo python setup.py bdist_mac

Step by step instructions:

I used mac ports for most of my python33 packages so I sticked to it for the rest. Libzmq is not available on macports but its dependencies are. So:

1) install libtool, autoconf, automake:

sudo port install libtool
sudo port install autoconf
sudo port install automake

2) grab the latest version of libzmq from https://github.com/zeromq/libzmq ( I downloaded the ZIP for sake of order ) and unzip/navigate to the folder

/libzmq-master

now the instructions provided in the INSTALL document in the folder are pretty clear, if you installed all the dependencies then you will be fine. run:

sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install

3) download the latest cx_freeze from https://bitbucket.org/anthony_tuininga/cx_freeze/downloads then unzip/untar navigate to folder and run:

sudo python setup.py build
sudo python setup.py install

now when compiling code for MacOSX that uses Python3.3 and PyQt5 you can run:

sudo python setup.py build

then navigate in the build folder and run the program as:

./nameoftheprogram

once you made sure this work then build the app or dmg (as you prefer) with:

sudo python setup.py bdist_mac --qt-menu-nib=/Users/username/Qt5.2.1/5.2.1/clang_64/plugins/platforms/

where the path is the path to your Qt5 installation. If I don't use the --qt-menu-nib option the app crashes on startup whereas the build works fine.

Hope this will help someone in the future.



回答2:

I got the same error and recompiling with the latest version of ZMQ (4.0.4) did not solve the issue.

However, by looking in the messages of the /Applications/Utilities/Console.app program, I could see that an extra command line option was given to my Python program. This command line option always started with -psn_0_ followed by a number. Apparently psn stands for Process Serial Number (see: http://hintsforums.macworld.com/showthread.php?t=11978).

My program uses the argparse package to parse the command line arguments and exited with an error because it didn't recognized the -psn option. I now filter it out before parsing with argparse and this solved my problem.