【前言】
运行python开发的程序,需要用户的电脑部署好python环境,而且还需要用户在命令行中输入命令来运行,当然你也可以写好bat脚本,让用户双击一下即可运行,但是依然还是需要用户电脑有python环境,对于普通用户来说,运行你的程序还得去部署环境,使用成本太高了。那么,python程序能不能做到像普通软件一样,让用户直接双击就能运行的呢?为了解决这个难题,pyinstaller应运而生,pyinstaller支持将python打包成window / Mac / GNU/Linux的应用软件, 算是覆盖了所有主流的操作系统了
一、PyInstaller安装
直接在命令行输入以下命令,等待安装完毕即可
pip install PyInstaller
提示安装完毕之后,可以输入以下命令验证一下是否安装成功
pyinstaller --version
二、PyInstaller命令参数
一般来说,直接执行执行命令就可以将python脚本生成exe文件
pyinstaller <option> myscript.py
其中,myscript.py是入口python脚本,执行时候,会把这个脚本依赖的其他python脚本一起打包成exe
1、option参数选项
这个参数选项比较多,每个都讲解下来篇幅太长,而且一般人也不一定用得上,需要的可以自己点进去这里查看,下面讲解一些比较常用的:
--distpath DIR
:指定exe最终生成的路径
--workpath WORKPATH
:指定编译时临时文件生成的路径
--clean
:在编译成exe之前,清除PyInstaller缓存并删除临时文件
--log-level LEVEL
:编译时控制台打印日志的信息量,取值其一:TRACE
, DEBUG
, INFO
, WARN
, ERROR
, CRITICAL
(default: INFO).
-D, --onedir
:指定生成一个包含exe可执行文件的单文件夹包(这是默认生成exe的方式)
-F, --onefile
:指定只生成单个exe可执行文件(即把上面文件夹下所有的文件都打包进单个exe中,但是实际运行时候,会解压到一个临时文件才运行,因此,这种方式启动会比-D会慢一丢丢)
--specpath DIR
:生成spec文件的保存路径, 默认保存到当前路径(spec文件生成之后,可以继续自定义修改,之后可以直接执行spec文件也行,执行方式:pyinstaller myscript.spec
)
-n NAME, --name NAME
:指定生成exe可执行文件与spec文件的名字,默认是传入的一个python脚本的文件名
--add-data SRC;DEST
:添加额外的非二进制文件到exe可执行文件中,添加多个路径时,这个选项可以使用多次;其中,SRC表示需要添加的非二进制文件,DEST表示需要添加到exe哪个层级目录下,比如:
--add-data "E:/DevTool/sswlTool-releaseGame/main/other;other/" --add-data "E:/DevTool/sswlTool-releaseGame/main/main1.py;."
--add-binary SRC;DEST
:添加额外的二进制文件到exe可执行文件中,同--add-data
,可以使用多次
-p DIR, --paths DIR
:指定查找import的路径(比如像使用PYTHONPATH
),可以用;
隔开指定多个路径。也可以使用这个选项多次
--hidden-import MODULENAME, --hiddenimport MODULENAME
:这个选项可以用多次,有时pyinstaller的分析器认为它已经找到了所有需要的模块,但实际却没有,这往往是存在隐藏的导入(hidden import)。当代码使用__import__
或exec
或eval
等函数时,可能会出现隐藏的导入。当扩展模块使用python/c API
进行导入时,也可能出现隐藏的导入。当这种情况发生时,分析器无法侦测,也不会有任何警告,只有在运行时才会出现错误,比如:运行exe,报错:
ModuleNotFoundError: No module named 'scipy._lib.messagestream'
修正方案:
pyinstaller --hidden-import=scipy._lib.messagestream myscript.py
--exclude-module EXCLUDES
:忽略排除指定模块或者包,注意是Python名,不是路径名,这个选项可以使用多次
--key KEY
:加密python字节码的秘钥
-d <all,imports,bootloader,noarchive>, --debug <all,imports,bootloader,noarchive>
:添加调试标识。 可以多次提供此参数
1)imports:为基础Python解释器指定-v选项,从而使该模块在每次模块初始化时打印一条消息,显示加载该文件的位置(文件名或内置模块)
2)bootloader:加载程序在初始化和启动exe可执行文件时发出进度消息, 用于诊断缺少import的问题
3)noarchive:不将冻结的python源文件作为归档存储到结果可执行文件中,而是将它们作为文件存储到结果输出文件夹中
4)all:包含上面所有
-c, --console, --nowindowed
:打开用于标准I/O的控制台窗口(默认)。 如果第一个脚本是“ .pyw”文件,则此选项无效。
-w, --windowed, --noconsole
:不显示标准I/O的控制台窗口。 如果第一个脚本是“ .pyw”文件,则将设置此选项
-i <FILE.ico or FILE.exe,ID or FILE.icns or “NONE”>, --icon <FILE.ico or FILE.exe,ID or FILE.icns or “NONE”>
:FILE.ico:将该图标应用于Windows可执行文件。 FILE.exe,ID,从exe中提取具有ID的图标。 FILE.icns:将图标应用于Mac OS X上的.app捆绑包。使用“无”不应用任何图标,从而使操作系统显示一些默认设置(默认:应用PyInstaller的图标)
三、实战案例
1、将python打包成单一exe文件
1)先看一下项目结构:
2)执行以下打包命令,避免每次都写一遍,我写成一个批处理脚本run.bat
pyinstaller -F -i .\main.ico --clean --name sswlTool --distpath . --runtime-tmpdir . .\main.py
其中: -F
所有依赖的python库都打包到单一的exe可执行文件中;-i
指定生成exe的图标,需要是.ico后缀的图片;--clean
指定每次打包前都清除缓存;--name
指定生成exe可执行文件的名字;--distpath
指定生成exe的目录;--runtime-tmpdir
指定exe运行时解压的生成_MEIxxxx
文件夹的路径,默认是你系统的临时文件路径,比如window:C:\Users\Administrator\AppData\Local\Temp;.\main.py
是程序入口的python脚本
注意:假如python代码中有用到命令行执行的代码,就不能指定-w选项,否则运行到执行命令行的代码会提示:无效句柄
,不过要是不设置-F时候,可以设置-w选项,执行发现不会报错;所以,我的结论是:-w 与 -F最好不要共存,要不可能会出问题
3)看看打包命令执行之后的目录结构变化:
4)双击运行sswlTool.exe,看看显示效果:
需要注意的是,我们打包没有把drawable等那些目录下的文件一起打包进exe,所以需要把那些资源一起提供给别人才可以正常运行
【注意】
可以通过--add-data
命令,将资源打包进exe中,比如:把背景图、icon那些打包进exe中,方便只提供一个exe给别人使用
pyinstaller --add-data ./drawable;drawable -F -w -i .\main.ico --clean --name batchModifyTool --distpath . .\main.py
其中,--add-data
后的./drawable
指定将当前目录下的drawable目录打包进exe中,;
隔开,之后drawable
目录指定exe运行时资源也是释放到drawable目录下,要是有多个目录需要打包进exe中,可以添加多次--add-data
命令
经过上面操作,是把资源成功打包进exe了,但是资源一般是释放到临时目录
中,要是我们代码中引用资源的路径写的是在当前exe运行目录查找,其实还是没法找到对应的资源, 需要加下面的代码去获得真实的资源路径:
def getResourcePath(relative_path):
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
# 设置窗口icon
self.setWindowIcon(QIcon(getResourcePath("drawable\icon.png")))
2、将python打包成一个包含exe的目录
1)执行命令
pyinstaller -w -i .\main.ico --clean --name sswlTool --distpath . --add-data .\channelPackageRes;channelPackageRes\ --add-data .\config;config\ --add-data .\drawable;drawable\ --add-data .\keystore;keystore\ --add-data .\lib;lib\ --add-data .\releaseChannelPackageRes;releaseChannelPackageRes\ --add-data .\unifySdkConfig;unifySdkConfig\ .\main.py
相比于打包成单个exe文件,去掉-F
、--runtime-tmpdir
,添加了-w
(前期测试,建议先不设置这个选项,那样就可以看到控制台的输出日志), 同时加了–add-data选项,这个主要的作用是复制指定的文件夹到生成exe的目录下而已,一般建议打包成包括exe目录的形式,因为少了解压过程,运行会更快
【延伸阅读】
一、auto-py-to-exe
auto-py-to-exe 是集成了pyinstaller的图形界面操作工具,可以通过简单的操作将.py文件打包成.exe文件,目前最新是v2.7.11,支持Python : 3.5-3.9
1、安装auto-py-to-exe
pip install auto-py-to-exe
2、运行auto-py-to-exe
安装完成之后,在命令行直接输入以下命令即可
auto-py-to-exe
3、看看运行效果