wxPython开发总结---将Python源代码打包成exe可执行文件
python的源代码要在没有安装/配置Python相关开发环境的电脑上运行,那么就需要使用工具对源代码进行打包,在windows上运行则必须打包成exe可执行文件,现在常用的打包工具有:
py2exe,PyInstaller以及cx-Freeze0
PyInstaller打包太慢,过程太长;
cx-Freeze可以说飞速打包;
py2exe打包相对比较麻烦,需要另外写一个Python的脚本文件.
下面使用py2exe工具打包Python源码,针对我打包过程中遇到的问题,给出解决办法.
使用py2exe打包需要写一个Python的脚本文件:
setup.py
#coding=utf-8 from distutils.core import setup import py2exe import glob # libRootPath = r'D:\ProgramStudy\python278' data_files = ["E:\python_p\logo.ico", (r'mpl-data', glob.glob(libRootPath+r'\Lib\site-packages\matplotlib\mpl-data\*.*')), (r'mpl-data', [libRootPath+r'\Lib\site-packages\matplotlib\mpl-data\matplotlibrc']), (r'mpl-data\images', glob.glob(libRootPath+r'\Lib\site-packages\matplotlib\mpl-data\images\*.*')), (r'mpl-data\fonts', glob.glob(libRootPath+r'\Lib\site-packages\matplotlib\mpl-data\fonts\*.*'))] setup( windows=[ { "script":'study_main.py', "icon_resources":[(1, "logo.ico")] }], options = { 'py2exe': { 'dll_excludes':['MSVCP90.dll', 'numpy-atlas.dll'], "includes": ["matplotlib.backends", "matplotlib.figure", "pylab", "numpy", "matplotlib.backends.backend_tkagg"], 'excludes': ['_gtkagg', '_tkagg', '_agg2', '_cairo', '_cocoaagg', '_fltkagg', '_gtk', '_gtkcairo', ] } }, data_files=data_files )
【说明】
(1)需要安装py2exe的Python库,可以使用pip install安装工具,也可以在官网下载安装;
(2)由于打包的过程会需要很多dll动态链接库文件,以及lib文件,需要我们在data_file中指定这些文件的位置,是在你电脑中Python安装目录下,由于我的项目中使用到了matplotlib来画图,所以会用到Python/Lib下matplotlib的lib和dll文件;
(3)第8行,指定了项目的logo所在的位置,需要时ico格式的图片,win7上logo无法正常显示,需要下载Greenfish Icon Editor Pro软件对你的icon文件进行处理,处理方法网上有;
(4)第17行,指定项目的入口文件,无论项目的文件有多少个,此处只需要指定入口的那个文件,就是有:
if __name__ == "__main__": main()
的文件;
(5)第23行,使用py2exe打包可能会有下面的错误:
Error: “MSVCP90.dll: No such file or directory”
此时就需要加第23行的这一句,本项目中使用matplotlib画图,而matplotlib是依赖numpy库的,同时可能会报numpy-atlas.dll no such file的错误,同样可以添加。
(6)numpy-atlas.dll的缺失,会导致程序打包正常,但点击打包之后的exe没有任何反应,可能失去少某些dll动态链接库文件,numpy-atlas.dll库文件在python安装目录下,搜索一下就找到了,另外,要是exe可执行文件点击之后没有反应,可以将其拖拽到cmd命令行中执行,会打印出出现的错误。
完成了上面的脚本文件之后,在命令行中执行打包操作:
python setup.py py2exe
就开始自动打包。
【注意】上面setup.py文件就是上面编写的打包脚本。
【其他需要说明的】
(1)兼容性:
不同的系统上文件系统的路径表示的格式是不太相同的,比如我们项目的用到的图片都放在项目根目录下的icon文件夹下,一种不太正确的路径定位方式:
import os.path main_dir = os.path.split(os.path.abspath(__file__))[0] iconRootPath = main_dir+os.sep+"icon"正确的定位方式:
import os.path iconRootPath = os.getcwdu()+os.sep+"icon"os.getcwdu() 指向了当前项目,也就是打包后exe可执行文件所在的目录,一般不要使用斜杠或者反斜杠作为分隔符,而是使用os.sep。
(2)项目结构
使用py2exe打包之后的文件夹中除了一大堆dll,lib文件之外,可以找到那个exe可执行文件,但我们点击之后,回报各种资源文件找不到,加入我们在项目中使用了图片,那么需要把图片文件夹额外拷贝到项目目录下,数据库文件等等,py2exe打包过程是不会把这些资源文件打包进来的,需要手动拷贝进来:
(3)sRGB警告
在win7系统中,微软提高了对图片质量的检测,项目中的图片可能会弹出下面的警告框:
"iccp known incorrect sRGB profile" 警告
这不是错误,但为了提高用户的体验,需要将这个框 去除,可以使用ImageMagick对图片进行转换,其实是该软件中magick.exe这个工具进行图片转换的:e.g. 使用magick.exe对D盘下的logo_sys.png进行转换,在cmd中执行:
magick.exe D:\logo_sys.png D:\logo_sys.png下面的程序可以批量处理文件夹下所有的图片文件:
import os # rootPath是需要转换的图片所在的根目录 rootPath = "D:/icon" # magick.exe所在的路径 commandTool = os.getcwdu()+os.sep+"tools"+os.sep+'magick.exe' # 获得rootPath目录下所有图片文件的全路径 def FindExamAllFiles(): tmp = [] for root, dirs, files in os.walk(rootPath): for filepath in files: imgFileFullPath = os.path.join(root, filepath) if imgFileFullPath.endswith('.png'): tmp.append(imgFileFullPath) return tmp if __name__ == "__main__": pngPathList = FindExamAllFiles() for pngPath in pngPathList: # 拼凑cmd命令 command = "{0} {1} {2}".format(commandTool, pngPath, pngPath) os.system(command)
要是我们的应用会涉及到用户自主导入图片的操作,为了保证不弹出sRGB警告框,可以在每次读入图片文件之后,调用下面的函数,首先对图片进行sRGB处理:
import platform # 处理文件夹中单个的图片 def convertsRGBImageFromTmp(iconFullPath): winVerName = platform.win32_ver()[0] if winVerName != None and winVerName.upper() == 'XP': return else: command = "{0} {1} {2}".format(commandTool, iconFullPath, iconFullPath) try: os.system(command) except: pass pass因为sRGB的检测是在win7以及之后版本的系统上才有的,在XP的系统上是无需进行该操作的,Python提供了platform这个库来检测当前系统的版本,我们可以使用platform.win32_ver()[0]获得版本的名称,并进行不同的操作。
(4)权限说明
正常情况下,windows系统允许你的应用从其他的路径下读取文件,但是一般不允许应用在 除应用根目录及以下的其他目录中写内容,即,你可以读取windows上大多数文件系统中的文件,只允许往os.getcwdu()目录下写内容,其他路径是不允许写操作的。