我有一个 Python 2.7/PyQt4 程序,我试图用 cx_freeze 冻结它。该程序还使用请求、串行、xml.etree.ElementTree 和集合。使用 cxfreeze-quickstart-2.7 生成的未修改 setup.py,我可以使用 macports 中的 Python 在 Yosemite 中成功构建控制台程序(python setup.py build)和 .app(python setup.py bdist_mac)。如果我直接从应用程序包或 dist 运行程序:
$ build/MacDISE-1.0.app/Contents/MacOS/macdise
$ dist/macdise
它完全按预期运行。如果我从命令行打开:
$ open -a /Users/jeffemandel/macdise/build/MacDISE-1.0.app
我得到了可怕的
LSOpenURLsWithRole() failed for the application /Users/jeffemandel/macdise/build/MacDISE-1.0.app with error -10810.
我解决了 Dan McCombs (distutils.util.get_platform, sys.arg) 提出的一些潜在问题,但这些似乎不是问题。通过蛮力试验和错误,我发现如果我将所有代码放在一个单独的模块中,只需导入该模块(而不实际调用它)就会导致 10810 错误,所以我认为从命令运行时它正在查找库行,但不是来自应用程序。我将 dist 目录放在拇指驱动器上,然后在另一台没有安装 Python、Qt4 等的 Mac 上运行它,得到了这个:
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
当我查看 dist 时,有一个文件 QtGui 与 /opt 中的文件大小相同。所以看起来失败是 dlopen(PyQt4.QtGui.so) 返回到 QtGui 库的硬编码路径。我猜解决方案很简单,但我还没有偶然发现它。
更新:我用 otool 查看了 build/Contents/MacOS/PyQt4.*.so 中的库,这些库都有 @executable_path(与 dist 中的硬编码路径相反)。我的笨蛋。所以我重复了移动程序的过程,只使用MacOS文件夹而不是dist文件夹,并在我妻子的MBP上从命令行执行macdise。问题出在我寻找包含文件的方式上。我将其更改为:
if getattr(sys, 'frozen', False):
uiName = os.path.join(os.path.dirname(sys.executable), "tabDISE.ui" )
else:
uiName = "tabDISE.ui"
它运行。可以为我节省一天的时间是一种自动将命令行执行时生成的错误消息转储到控制台日志的方法。如果有人知道如何做到这一点,那将是一个很大的帮助。