先贴上pyinstaler的官网指南,很多使用方法可以直接查到:
https://pythonhosted.org/PyInstaller/usage.html
-
pyinstaller的安装:
在自己的环境下运行:
pip install Pyinstaller
有什么错误就根据错误提示去查,这个容易解决~
-
pyinstaller的初步使用:
进入程序所在的目录下,命令行直接运行:
pyinstaller XX.py # XX换成自己的文件名
执行可以在该目录下得到两个文件夹dist和build,还有一个XX.spec文件,需要的可执行程序就在dist文件夹下。如果你的python程序没有使用外部文件,这时候进入dist文件夹下,命令行中使用 ./ 执行该文件即可运行。
遇到一些错误如no module ...,很有可能是pyinstaller没有自动导入你调用的第三方库,这里贴几篇文章作为参考。
https://www.jianshu.com/p/bf07565f0090
https://www.xncoding.com/2015/09/07/python/pyinstaller.html
-
pyinstaller分步生成可执行文件
上一步中我们可以看到生成了一个spec文件,简单情况下,我们使用pyinstaller的一些options选项就足够了,但在一些其他情况下,我们可以通过修改spec文件,来对我们生成可执行文件的过程进行自定义。
生成spec文件可以通过命令:
pyi-makespec options name.py
其中,options和pyinstaller的options几乎一致,可以参考官网文档:
https://pythonhosted.org/PyInstaller/man/pyi-makespec.html?highlight=pyi
这里,我使用的命令如下:
pyi-makespec present_fasttext_txt.py -F --hidden-import fasttext.model
这样生成的就是一个单一执行文件
生成的spec可以打开编辑:
# -*- mode: python -*-
block_cipher = None
a = Analysis(['present_fasttext_txt.py'],
pathex=['/home/km/PycharmProjects/fasttext'],
binaries=[],
datas=[],
hiddenimports=['fasttext.model'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='present_fasttext_txt',
debug=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=True )
因为加了-F参数,所以没有coll内容(查阅官网文档可以知道这个是用来在dist目录下生成程序文件夹的)
当我们需要添加资源文件时,在datas那个list中添加相应tuple,tuple的元素是两个字符串,第一个意为调用的资源文件在系统下的路径,第二个是该文件相对于生成的程序的路径,添加之后该spec文件如下:
# -*- mode: python -*-
block_cipher = None
a = Analysis(['present_fasttext_txt.py'],
pathex=['/home/km/PycharmProjects/fasttext'],
binaries=[],
datas=[('comment_fasttext_isinv.model.bin','.'),('comment_fasttext_isneg.model.bin','.'),('comment_fasttext_issug.model.bin','.'),('comment_fasttext_isbug.model.bin','.'),('comment_fasttext_ispraise.model.bin','.')],
hiddenimports=['fasttext.model'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='present_fasttext_txt',
debug=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=True )
可以看到我修改了datas部分,由于我调用的文件就在我的当前目录下,所以我直接写的文件名,如果调用其他目录下的文件,要写全名的,后面的‘.’,表示它存在程序的根目录下。
这样修改完了,执行:
pyinstaller present_fasttext_txt.spec
即可。
之后进入dist文件夹下,发现可执行程序比较大,大概有80M,应当是把资源文件打包进去了。执行程序,发现报错。显示找不到文件,经过排查发现原来还有关键的一步没做。
-
打包成一个exe之后资源文件的路径问题
之前的py程序中,由于资源文件直接放在项目根目录下面,所以调用的时候直接用的文件名。这导致,后面打包成exe文件的时候,调用资源文件时会在dist文件夹下搜索文件,当然,我的文件打包到exe文件中了,这样调用显然会出现找不到相应文件的错误,所以,我们还要对python程序部分进行路径上的修改。
参考博文:
https://www.xncoding.com/2015/09/07/python/pyinstaller.html
https://my.oschina.net/u/3018050/blog/1610937
要定义一个读取相对路径的函数:
import os, sys
def resource_path(relative_path):
"""
定义一个读取相对路径的函数
"""
if hasattr(sys, "_MEIPASS"):
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
我之前的调用示例如下:
classifier1 = fasttext.load_model("comment_fasttext_isinv.model.bin", label_prefix='__label__')
修改之后为:
classifier1 = fasttext.load_model(resource_path("comment_fasttext_isinv.model.bin"), label_prefix='__label__')
修改程序后,再打包,一切ok~