您的位置:首页 > 移动开发

64位macOS下使用py2App打包PyQt4程序

2011-05-16 20:30 911 查看
这个问题困扰了我两天,今天终于将它解决了。现在把这两天来所遇到的困难和解决办法记录在此,以便自己以后查询,同时也希望能够对遇到同样问题正在困扰着的朋友起到一点作用。(虽然大都是很基础得东西,而且有些自己还是一知半解,若有说的不是的地方,望各位朋友见谅并留言帮助改正,先谢谢了。) 

 

本文内容主要分为以下几个部分:

1.为什么选用py2app?

2.py2app的安装和使用方法

3.使用py2app对macOS 64位下的Python程序打包应该注意的问题。

4.PyQt4程序打包的困扰。

5.打包后中文内容变成乱码以及pyQt程序中字符串的操作出现异常的问题。

 

 

 

正文

1.为什么选用py2app?

据我所知道的,能够用在MacOS上的打包工具主要有cx_freeze、pyInstaller、py2app(py2exe变种)等等。

 

① cx_freeze: 我首先尝试的打包工具,安装后使用后不久,就放弃了。(现在已经忘记是出现什么问题而导致无法打包成功了,不过不是本文重点,在此就不介绍了。)

② pyInstaller:pyInstaller目前只支持win(32/64bit),linux,macOS(32bit)、我的mac是10.6.7版本的,是64位的。所以无法使用。(开始的时候一直以为系统是32位的,各种尝试后无果,最后才发现是64位系统,于是放弃pyInstaller)

③ py2app:py2app是py2exe在macOS下的变种,使用方法和py2exe几乎一样。关键的是在py2app文档(貌似只有英文的)中并没有说不支持mac64位系统,于是我就着手使用py2app

 

附:

①.获取当前系统默认python版本以及执行路径

在终端输入

file `which python`

你可以获得当前默认python的各种子版本(姑且这样叫)以及执行路径,例如:

ou-i-no-iMac:~ ww$ file `which python`
/Library/Frameworks/Python.framework/Versions/2.7/bin/python: Mach-O universal binary with 3 architectures
/Library/Frameworks/Python.framework/Versions/2.7/bin/python (for architecture i386):   Mach-O executable i386
/Library/Frameworks/Python.framework/Versions/2.7/bin/python (for architecture ppc7400):    Mach-O executable ppc
/Library/Frameworks/Python.framework/Versions/2.7/bin/python (for architecture x86_64): Mach-O 64-bit executable x86_64
 

如果以上结果中包含

/Library/Frameworks/Python.framework/Versions/2.7/bin/python(for
architecture i386):  Mach-O executable i386

一项的话,说明你可以在64位系统上使用32位的python,使用方法如下(在终端):

arch -i386 python yourPythonFile.py
原本利用此方法可以使用pyinstaller等只支持32位MacOS的打包工具,不过因为我使用macPorts自动安装的py2.7-PyQt4,以至于能够参照Qt库的python2.7并不包含“arch -i386 python”,所以放弃使用32位python进行编译打包工作。[/code]
如果有朋友是自己手动安装的,并成功满足以上两个条件(1.含32位python;2.32位python可以访问Qt库)的话,可以尝试下用"arch -i386 python"和pyinstaller来打包程序。

 

至于更改默认的python版本,有两种方法:

•使用python_select

首先你需要安装python_select,之后在终端执行类似下面的语句:

  
sudo python_select python27
 

你就可以将系统默认的python版本改为python2.7

•修改mac环境变量

比如当你安装了多个python2.7的时候(手动安装和使用macPorts安装),而你当前默认的python2.7并不能参照Qt库的话,你就需要修改系统环境变量了。修改方法如下(在终端):

 查看

. .bash_profile
env
 

 编辑

 

pico .bash_profile
 

在编辑状态下将PATH的值修改成你想要的Python2.7的路径,保存,退出即可。

 

②.利用python获取系统的位数

     执行下列语句

]import sys
print("%x"%sys.maxint)
 

  如果结果是7fffffffffffffff的话系统就是64位的,

  如果结果是7fffffff就说明系统是32位的。

 

 

 

 

2.py2app的安装和使用方法(非MacOS 64位系统的一般情况)

   py2app的安装其实很简单,你可以使用macports一键式安装,也可以下载其源代码,使用"python setup.py install"安装。

   我两种方法都试了下,不过为了安全起见(老实说有点不信任macports),我觉得自己手动编译源代码来得好一些(没有特殊理由,只是觉得不是自己亲手干的活总担心出问题,尤其是当你可能会遇到莫名其妙的问题的时候。

 

   好了,如果你成功安装好py2app之后,你就可以开始打包源代码了。

   正常的打包过程分为以下几步(在终端):

   ①.使用cd命令进入到你的源程序所在的目录

   ②.执行语句py2applet --make-setup yourPython.py

   ③.如果不是第一次打包该程序,你最好先删除先前的旧版本,使用“rm -
4000
rf build dist”语句

   ④.修改第②步骤生成的setup.py文件,将源程序所需要用到的库包含进去。其中:

       •DATA_FILES参数是对应资源文件(比如PyQt的ui文件)

       •OPTIONS中可以包含所需要用到的库。

       具体示例如下

from setuptools import setup
APP = ['yourPython.py']
DATA_FILES = ['gui.ui']
OPTIONS = {'argv_emulation': False,'includes':['sip', 'PyQt4', 'PyQt4.QtGui', 'PyQt4.QtCore', 'PyQt4.uic', 'sitecustomize']}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
 

   ⑤.最后执行打包:python setup.py py2app(有的文章中会在语句最后加上flag"-A",这个flag具体该什么时候用,我在后面的文章中会给予说明)

 

 

 

 

3.使用py2app对macOS 64位下的Python程序打包应该注意的问题

 

  按照前文所示方法在macOS 64位的环境下是无法正常打包的。

  原因就在于打包程序setup.py中的[argv_emulation]参数并不支持64位系统。强行打包的话系统会提示 “当前python是64位的,请使用VERSIONER_PYTHON_PREFER_32_BIT参数进行32位的转化”等类似的错误。

  在网上找将默认python转换位32位的方法,大多数文章都描述了两种方法:

  1.在命令行执行:export VERSIONER_PYTHON_PREFER_32_BIT=yes添加系统环境变量达到目的

  2.在命令行执行:defaults write com.apple.versioner.pythonPrefer-32-Bit-bool
yes 设置默认pyhon版本

  两种方法我都试了,可是不知道是因为什么原因两种方法都没能奏效(我推测应该是当时的默认Python版本(我用MacPort装的)中不带32位的版本,也就是在第1节中查看python子版本时,返回的结果中没有“/Library/Frameworks/Python.framework/Versions/2.7/bin/python (for architecture i386):   Mach-O executable i386”这一项)

  总之,两种方法都失败了。于是我就只好将setup.py中的[argv_emulation]参数的值改为False,其他代码不变,试着打包,成功。

  打包程序setup.py的代码如下:

from setuptools import setup
APP = ['yourPython.py']
DATA_FILES = ['gui.ui']
OPTIONS = {'argv_emulation': False,'includes':['sip', 'PyQt4', 'PyQt4.QtGui', 'PyQt4.QtCore', 'PyQt4.uic', 'sitecustomize']}
setup(
app=APP,
version = '1.0',
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
 

 

 

 

4.PyQt4程序打包的困扰。

 

 ①经过第3节的修正,好的,终于看到了希望,程序成功打包成MacOS的可执行程序.app文件了。试着点击,运行,竟然运行失败,系统弹出“XXX因不可预期的原因被终止运行”等类似的警告。这是什么原因呢?

 

  原来使用了Qt编写界面的应用程序要想在Mac上运行,还需要额外的一个文件———“qt_menu.nib”

  我们需要在已安装好的PyQt4的目录中找到“qt_menu.nib”文件,然后将其复制到应用程序的可执行文件(即之前打包好的.app文件)内。

  方法是鼠标右键点击[.app]文件,选择查看包的内容(中文macOS不知道是怎样写的,总之大概意思就是这样),然后准备好的qt_menu.nib复制到包文件内的Contents/Resources/的目录下。之后再双击[.app]文件启动应用,成功!!

 

 ②终于成功了,赶紧在其他人的机器(未配置相应环境)上运行下试试,同样成功启动并运行。

  什么?你打好的包失败了?那你和先前的我一样悲剧,在打包的时候在"python setup.py py2app"后面添加了"-A"flag。也就是说打包时候的命令为

  
python setup.py py2app -A
 

 这样打包出来的文件只是应用程序的一个别名,在配置了相同环境的机器上可以运行(应该吧!),可是在未配置好环境的机器上就无法运行了。

  不使用别名flag“-A”的情况下一般打包出来的[.app]文件会达到30M(至少我的所有程序都是这样),虽然有点庞大,不过我不知道有什么更好的方法,只能将就了,再怎么说能成功运行才是关键。

 

 

 

5.打包后中文内容变成乱码以及pyQt程序中字符串的操作出现异常的问题。

 

  细心的朋友应该早就发现上文中的setup.py中,包含的头文件里面多出来一个“sitecustomize”。下面就来说下这个文件的作用。

  程序打包之前,直接通过命令行运行python yourPython.py时,生成的Qt界面能够完美的显示中文,可是程序打包后有部分甚至全部中文都无法显示,变成乱码。

  这时候你就需要在源程序yourPython.py中添加“sitecustomize”这样一个头文件。印象中你在finder中搜索下就能找到这个文件,如果没有的话自己动手写一个也行。代码如下:

import sys
reload(sys)
sys.setdefaultencoding('UTF-8')
 

然后将准备好的sitecustomize.py放入你的程序能够参照的目录下(推荐python库中的site-packages目录,比如我的电脑的话放入“/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages”目录下。这样所有的python程序都能参照这个文件)

完成上述的操作的话,打包后的程序界面就应该能正常显示中文以及其他非英语字符(比如日文,韩文)了。

 

最后,关于“PyQt程序中字符串的操作出现异常的问题”,因为从发现问题到写下本博客的时候已经隔了有一段时间了,我忘记时什么问题了。不过印象中和字符编码有关,总之记住将所有字符转化为utf-8再处理就应该没有问题(Qt中使用QTextCodec来进行转换)。

 

从开始想写下这篇blog,到开始动手写,到最后完成竟然用了半个多月。。我自己都无语了。。

主要是最近工作太忙了,都没得时间。昨天加班到12点,还是开会开到那么晚,真是效率啊!

分享到
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息