1 概述
python脚本运行需要python,以及依赖的各种库。制作Exe程序,就是将该脚本、python程序及其依赖的第三方库打包成一个可执行文件。
这就使用到一个专用工具,Pyinstaller。该程序本身也是python下的一个程序,需要在python的环境中安装该程序,然后进行打包。
2 安装pyinstaller
与其他python下的程序安装类似,详细参考我另一篇文章:https://blog.csdn.net/kevinshift/article/details/88807868。
3 打包示例
进入要打包的环境中,输入以下命令
(tensorflow) C:\Users\Kevin>pyinstaller -F PythonTester.py
其中-F表示只打包成一个Exe文件。
出现如下命令时表示成功。
成功后默认会生成以下文件:
(1)pyTest.exe,默认位于命令行当前路径下的dist文件夹中。上例中位于:C:\Users\Kevin\dist 中。
(2)在C:\Users\Kevin中还会生成一个build文件夹,其中给出了该程序中间生成的一些东西。其中有一个文件提示了没有找到的库、被忽略的库等信息,但这只是作为一个参考。没找到会被忽略了,并不一定影响最后程序的运行,还要看最后exe的结果来说。
(3)PythonTester.spec文件。在C:\Users\Kevin中生成一个spec文件,默认名称与py文件同名,上例中为PythonTester.spec。该文件后面会详细说明。
4 打包生成文件形式
pyinstaller打包文件包含两种情况:
(1)将py文件、python及第三方库全部打包为一个单独的Exe中。
(2)将以上三者打包形成一个文件夹,文件夹中包含一个Exe,一个python,及其依赖的第三方库。
二者通过不同的选项
二者的优劣对比:
(a)启动时间
单一可执行文件比文件夹的启动时间要长
因为当程序运行时,单一的可执行文件需要解压程序的第三方依赖文件到临时文件夹中。
(b)文件结构
单一可执行文件的文件结构和工程目录是一样的,但是生成文件夹就不一样了,若程序中包含相对路径,这个相对路径自然基于的是文件夹目录,这点需要注意。
在打包过程出现问题时,可以生成文件结构,进入细致查看发生了什么。
5 pyinstaller文件如何打包
5.1从哪打包
将python文件、python程序及程序相关的第三方库都打包。这样该包就可以在别的地方独立运行了。
python文件的打包是基于某个运行环境的,因此必须切到那个环境下,上例中我们在tensorflow中。而环境的第三方库位于环境(环境位于C:\ProgramData\Anaconda3\envs)的Lib\site-packages文件夹下。所以本例中就是位于:C:\ProgramData\Anaconda3\envs\tensorflow\Lib\site-packages
5.2 找哪些文件,如何找的
打包过程中,pyinstaller不会将所有的都打包,而是将本文件运行所需要的第三方库打包的。
当然,还有我们自己的程序运行,可能也需要一些配置文件等,有二进制文件、文本文件等形式。这些如何打包呢?
第三方库、连同自己的文件,有几种形式,pyinstaller按照不同方法得到:
(1)python文件。
这个是通过分析该python文件,分析其显示import的库,并递归的去寻找这些python文件,依次将其包含。
当然这里有一个问题,对于隐式调用的则不能被包含。此时打包后的exe将会出现无法找到某些库的情况。此时需要手动加入包含模块,方法见spec文件的hiddenimports介绍(当然也可以命令行、等效的)。
在打包的过程中,这个是问题最多的地方,表现形式也多种多样,但很多都是这种情况引起的,在另一篇文章中将介绍tensorflow中隐式调用的模块的情况。
(2)二进制文件
二进制文件是无法通过上面的方法分析到的,必须通过binaries指定,告知从哪打包到哪。详见spec文件中对于binaries的介绍。
(3)其他数据文件
跟二进制文件类似,通过datas指定,详见spec中的datas介绍。
6 打包程序运行原理
6.1 带文件夹的Exe运行原理
其实这个文件夹就是一个小型的环境,是之前那个打包的环境的一个子集,可以看下他的目录结构,跟环境是很像的。
Exe中将python文件已经封装了,其中有指定运行该文件,然后调用python和第三方库。
其中python文件和第三方库,自己的配置文件等都放在文件夹下。
而Exe封装了对于python文件的逻辑和调用pthon的这个运行逻辑。
运行exe,将完成调用python程序,执行python脚本。
6.2 单独Exe运行原理
Exe中增加了一个类似于代理或boot的程序段,运行后,他会将上面所说文件夹中的python、第三方库、配置文件等东西解压到一个临时文件夹中。
解压之后,就跟上面带文件夹的情况类似了。
之后再调用pthon,运行python脚本。
当关闭该程序时,Exe会将临时文件夹删除。
默认情况下,这个临时文件夹的路径位于:C:\Users\KevinAppData\Local\Temp文件夹下,这个临时文件夹名称为_MEIxxxxxx,其中XXXX为一个随机数。
注意:正常情况下,这个临时文件夹会被删除,但是如果exe被意外强制关闭,将无法被删除,那么你的c盘就会被占用。笔者之前就是遇到该中情况,该exe被我的程序调用,后被程序强制关闭。
也可以更改这个文件夹的路径,方法通过–runtime-tmpdir设置,或者在spec文件中runtime_tmpdir中设置(和exe同一个文件夹下,设置为‘.’)。
7使用Spec文件打包
7.1 概况
打包时有很多控制选项,可以通过打包命令行使用。也可以通过Spec文件指定这些选项,这样不需要每次输入长长的选项了。效果上二者是等效的。
其实在命令行打包时,pyinstaller会自动的生成一个spec文件,保存在命令行的当前路径下。
(1)使用spec文件
(tensorflow) C:\Users\Kevin>pyinstaller PythonTester.spec
(2)生成Spec文件
(tensorflow) C:\Users\Kevin>pyinstaller -F PythonTester.py
如运行上面的命令时,则在C:\Users\Kevin下自动生成一个名称为PythonTester.spec的文件,其内容如下:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['X:\\python\\PythonTester.py'],
pathex=['C:\\Users\\Kevin'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ