version.txt来源参考:!!!胜天半子_王二_王半仙的文章:pyinstaller打包exe,设置发布者,版权,产品名称等版本信息
资源在最后面!!!
准备
使用前导入包:
import os
import subprocess
安装pyinstaller:
pip install pyinstaller
# 使用清华源则是:
pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple
pyinstaller参数
inp = f"D:\\Desktop\\EX\\PyCharmEX\\Mini_program\\Netdisplay.py" # .py的目标路径
outname = 'Netdisplay' # 自定义名称 # 不支持中文
inppt = inp.split('\\')[-1][:-3] # 获取.py目标文件的文件名(不包括后缀名)
outp = currentpath + "\\exe" # .exe的保存路径
outws = currentpath + "\\workspec" # work和spec保存路径
versionfile = currentpath + "\\version.txt" # 版本信息文件路径
pyinstaller --distpath="{outp}" --workpath="{outws}" --specpath={outws} -w -F --version-file {versionfile} "{inp}"
--distpath 为打包生成的exe文件保存路径,默认存放在当前目录下的dist
目录中
--workpath 为输出的所有临时文件指定存放目录,默认为当前目录下的build
目录
--specpath 为.spec文件位置
--version-file 需要指定版本信息文件的路径
limit报错情况处理
打包报错时出现With the default recursion limit (1000)...时,需要在目录的*.spec文件的开头增加import sys\n sys.setrecursionlimit(sys.getrecursionlimit()*5) 两段语句,保存并在命令行执行pyintaller *.spec
打包报错时出现
With the default recursion limit (1000)...
需要在目录的*.spec文件的开头增加
import sys
sys.setrecursionlimit(sys.getrecursionlimit()*5)
保存并在命令行执行
pyintaller *.spec
自动化处理limit报错的情况
打包
inp = f"D:\\Desktop\\EX\\PyCharmEX\\Mini_program\\Netdisplay.py" # .py的目标路径
outname = 'Netdisplay' # 自定义名称 # 不支持中文
inppt = inp.split('\\')[-1][:-3] # 获取.py目标文件的文件名(不包括后缀名)
outp = currentpath + "\\exe" # .exe的保存路径
outws = currentpath + "\\workspec" # work和spec保存路径
versionfile = currentpath + "\\version.txt" # 版本信息文件路径
# 修改需要打包的.py文件路径和.exe保存路径(使用绝对路径 方便后续的cmd命令执行)
print(f'正在打包{inppt}...请勿关闭程序...')
yYn = input('是否添加版本信息?(y/n)')
if yYn == 'y' or yYn == 'Y': # 添加版本信息
if inppt == outname:
cmd = f'pyinstaller --distpath="{outp}" --workpath="{outws}" --specpath={outws} -w -F --version-file {versionfile} "{inp}"'
else:
cmd = f'pyinstaller --distpath="{outp}" --workpath="{outws}" --specpath={outws} -w -F --version-file {versionfile} "{inp}" -n "{outname}"'
else: # 不添加版本信息
if inppt == outname:
cmd = f'pyinstaller --distpath="{outp}" --workpath="{outws}" --specpath={outws} -w -F "{inp}"'
else:
cmd = f'pyinstaller --distpath="{outp}" --workpath="{outws}" --specpath={outws} -w -F "{inp}" -n "{outname}"'
a = subprocess.getoutput(cmd)
# cmd中的pyinstaller更多用法请百度
# -c为有控制台的打包,使用情况为.py文件语句中有input()等
# -w为无控制台的打包
# 执行cmd命令并将cmd的输出结果保存为字符串a
如遇到limit报错情况
limit = 'With the default recursion limit (1000)' # limit报错
# 当出现limit报错【即出现With the default recursion limit (1000)...语句】时,执行后面的elif limit in a: 语句
suful = 'Building EXE from EXE-00.toc completed successfully.' # 打包成功
# 同理,当打包成功时,执行if suful in a:语句
# 报错或成功语句可能有所不同!!!
print(a)
if suful in a: # 当打包成功时
print('===>>>successful!!!<<<===')
pass
elif limit in a: # 当出现limit报错时
print('因spec出现limit限制,更改并重新运行......')
path = outws + f'\\{inppt}.spec'
data = 'import sys\n' \
'sys.setrecursionlimit(sys.getrecursionlimit()*5)\n'
# 将.spec文件保存在path中,将需要在.spec开头增加的文本保存为data
ext = os.path.splitext(path) # 将文件名路径与后缀名分开
newname1 = ext[0] + '.txt'
os.rename(path, newname1)
# 将.spec文件改为.txt文件
with open(newname1, "r+") as f:
old = f.read()
f.seek(0)
# 跳至文件开头
f.write(data)
# 写入数据
f.write(old)
ext = os.path.splitext(newname1) # 将文件名路径与后缀名分开
newname2 = ext[0] + '.spec'
os.rename(newname1, newname2)
# 恢复.spec文件的命名
b = os.system(f'pyinstaller {outws}\\{inppt}.spec')
# 执行cmd命令
version.txt详细内容
# UTF-8
VSVersionInfo(
ffi=FixedFileInfo(
#filevers和prodvers应该始终是包含四个项的元组:(1、2、3、4),将不需要的项设置为0
filevers=(1, 2, 1, 0), # 文件版本******,鼠标悬浮exe会显示,也显示在 详细信息-文件版本,这个是检测版本的依据
prodvers=(4, 6, 9, 4), # 生产商,未见显示在哪里
mask=0x3f, # 两个位掩码
flags=0x0,
OS=0x4, # 为其设计此文件的操作系统,0x4-NT,无需更改它
fileType=0x1, # 文件的常规类型,0x1-该文件是一个应用程序
subtype=0x0, # 文件的功能,0x0表示该文件类型未定义
date=(0, 0) # 创建日期和时间戳
),
kids=[
StringFileInfo(
[
StringTable(
u'040904B0',
[StringStruct(u'CompanyName', u'HZGT'), # 鼠标悬浮exe会显示 # 公司
StringStruct(u'FileDescription', u'Ndp 右下角悬浮窗展示网速和本次流量使用总量'), # 文件说明,鼠标悬浮exe会显示,也会显示在 详细信息-文件说明 # 文件描述
StringStruct(u'FileVersion', u'1.2.1'), # 没见哪里显示
StringStruct(u'InternalName', u'SVN'),
StringStruct(u'LegalCopyright', u'HZGT版权所有'), #版权,会显示在 详细信息-版权
StringStruct(u'OriginalFilename', u'Netdisplay'), #原始文件名,会显示在 详细信息-原始文件名
StringStruct(u'ProductName', u'Netdisplay'), #产品名称,会显示在 详细信息-产品名称
StringStruct(u'ProductVersion', u'1.2.1')]) #产品版本,会显示在 详细信息-产品版本
]),
VarFileInfo([VarStruct(u'Translation', [2052, 1200])]) # 语言,中文简体
]
)