1

I have a Python 2.7/PyQt4 program that I am attempting to freeze with cx_freeze. The program also uses requests, serial, xml.etree.ElementTree, and collections. Using the unmodified setup.py generated by cxfreeze-quickstart-2.7, I can successfully build as both a console program (python setup.py build) and an .app (python setup.py bdist_mac) in Yosemite using Python from macports. If I run the program directly either from the app bundle or the dist:

$ build/MacDISE-1.0.app/Contents/MacOS/macdise
$ dist/macdise

It runs exactly as expected. If I open from the command line:

$ open -a /Users/jeffemandel/macdise/build/MacDISE-1.0.app

I get the dreaded

LSOpenURLsWithRole() failed for the application /Users/jeffemandel/macdise/build/MacDISE-1.0.app with error -10810.

I worked through a number of potential issues raised by Dan McCombs (distutils.util.get_platform, sys.arg), but these don’t seem to be the problem. Through brute force trial and error, I found that if I put all of my code in a separate module, simply importing that module (without actually invoking it) causes the 10810 error, so I figured it was finding a library when run from the command line, but not from the app. I put the dist directory on a thumb drive and ran it on another Mac that doesn't have Python, Qt4, etc installed, and got this:

packages/cx_Freeze/initscripts/Console.py", line 27, in <module> File "macdise.py", line 4, in <module>
File "ExtensionLoader_PyQt4_QtGui.py", line 11, in <module>
ImportError: dlopen(/Volumes/NO NAME/dist/PyQt4.QtGui.so, 2): Library not loaded: /opt/local/Library/Frameworks/QtGui.framework/Versions/4/QtGui
Referenced from: /Volumes/NO NAME/dist/PyQt4.QtGui.so
Reason: image not found

When I look in dist, there is a file QtGui that is the same size as the one in /opt. So it seems the failure is dlopen(PyQt4.QtGui.so) returning a hard-coded path to the QtGui library. I'm guessing the solution is simple, but I haven't stumbled across it yet.

Update: I looked at the libraries in build/Contents/MacOS/PyQt4.*.so with otool, and these all have @executable_path (as opposed to hard-coded paths in dist). My stupid. So I repeated the process of moving the program, only using the MacOS folder rather than the dist folder, and executing macdise from the command line on my wife's MBP. The problem turned out to be in the way I was looking for the included_files. I changed this to:

if getattr(sys, 'frozen', False):
    uiName = os.path.join(os.path.dirname(sys.executable), "tabDISE.ui" )
else:
    uiName = "tabDISE.ui"

and it runs. What would have saved me a day would be a way to automagically dump the error message generated when executing from the command line to the console log. If someone knows how to do this, it would be a big help.

Thomas K
  • 39,200
  • 7
  • 84
  • 86

0 Answers0