要在未安装/配置相关开发环境的计算机上运行源代码,需要使用工具对源代码进行打包。 如果想在电脑上运行,必须将其打包成exe可执行文件。 常用的打包工具有:
,和CX-
打包速度太慢,流程太长;
CX-可以说是很快就打包好了;
打包比较麻烦,需要额外编写一个脚本文件。
下面使用工具来打包源码,并给出我在打包过程中遇到的问题的解决方案。
要使用打包,需要编写脚本文件:
安装程序.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)对于需要安装的库,可以使用pip安装工具,也可以从官网下载安装;
(2)由于打包过程中会需要大量的dll动态链接库文件和lib文件,所以我们需要指定这些文件在你电脑的安装目录中的位置。 由于我的项目中用它来画图,所以会用到/Lib下的lib和dll文件;
(3)第8行指定了项目标志的位置。 如果需要的话,ico格式的图片在win7上无法正常显示。 您需要下载 Icon Pro 软件来处理您的图标文件。 处理方法可在线查阅;
(4)第17行指定工程的入口文件。 无论项目中有多少个文件,这里需要指定entry的文件只有:
if __name__ == "__main__": main()
文档;
(5)第23行,使用打包时可能会出现以下错误:
错误:“.dll:没有这样的文件或”
这时需要添加第23行这句话。这个项目使用了绘图,但是依赖于numpy库。 同时可能会报numpy-atlas.dll no such file的错误,也可以添加。
(6)缺少numpy-atlas.dll会导致程序可以正常打包,但点击打包后的exe没有反应,并且可能会丢失部分dll动态链接库文件。 numpy-atlas.dll库文件位于安装目录中。 搜索后即可找到。 另外,如果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.()指向当前项目,即打包后exe可执行文件所在目录。 一般情况下,不要使用斜杠或反斜杠作为分隔符,而是使用os.sep。
(二)项目结构
打包后的文件夹中除了很多dll和lib文件之外,还可以找到exe可执行文件,但是我们点击后却返回找不到各种资源文件。 补充一下,我们在项目中使用了图片,那么需要将图片文件夹复制到项目目录下,数据库文件等,这些资源文件在打包过程中不会被打包,需要手动复制到:
(3) sRGB警告
在win7系统中,微软改进了对图片质量的检测,项目中的图片可能会弹出如下警告框:
“ sRGB”警告这不是一个错误,但是为了提高用户体验,这个框需要去掉,可以使用图像转换,其实就是软件中的.exe工具转换图像:
例如使用.exe转换D盘下的.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系统上无需执行此操作。 该库用于检测当前系统版本。 我们可以使用 .()[0] 来获取版本的名称,并且操作不同。
【下载】.exe文件及转换代码文件下载
(4)权限说明
一般情况下,系统允许你的应用程序从其他路径读取文件,但一般不允许应用程序在应用程序根目录及以下以外的目录中写入内容,也就是说,你可以读取大多数文件系统中的文件。允许向os.()目录写入内容,其他路径不允许写入。