构建spec文件、打包PyQt程序为exe,UPX压缩一次搞定

       构建spec文件,打包你的PyQt程序,并借助强大的UPX工具对可执行文件进行压缩!本文将为你呈现一场代码与工具的完美融合,助你打造精简高效的应用程序。了解如何构建spec文件、设置打包参数,以及利用UPX工具压缩可执行文件。无需烦恼,让我们一同踏上这个引人入胜的打包之旅,开启你的软件开发新篇章!

打包完成后,若还希望将可执行程序升级为程序安装包。别担心,可以参考我的下一篇文章:无缝安装体验!打造自定义PyQt程序安装包与应用程序安装向导 这篇文章中为你提供详细指南。通过我的指导,你将学会如何将打包好的应用程序转化为高级、用户友好的安装包。从设置安装向导,到自定义图标和界面,我将一步步引导你,让你的应用程序脱颖而出。

一、一般打包步骤

  1. 查看项目的依赖包:Terminal终端输入:pip freeze > reqirments.txt
  2. 在项目 Terminal 终端操作,安装 pyinstaller库pip install pyinstaller
  3. 输入命令,最后生成exe文件 pyinstaller各种参数
pyinstaller -xx xxx.py
pyinstaller-F setup.py 
-F:参数表示覆盖打包,这样在打包时,不管我们打包几次,都是最新的,这个记住就行,固定命令。 
pyinstaller -F -w setup.py
-w:不会在启动程序的时候瞬闪黑洞洞的控制台了!默认得闪一下控制台
pyinstaller -F -w-i wind.ico setup.py
-i xx.ico :添加图标
111

二、spec文件打包

2.1 自动生成 .spec 文件

​ Terminal 终端任意打包一个项目文件,执行pyinstaller -F temp.py

​ 打包结束后,将在当前目录下生成两个文件夹(bulid、dist)和一个文件setup.spec,此时我们删除两个文件夹(bulid、dist),只需要关注 setup.spec 文件。

​ 简要介绍.spec 中主要关注的地方。 如需要详细了解请看下文:.spec 文件参数详细介绍

# -*- mode: python ; coding: utf-8 -*-
 
block_cipher = None
 
 
a = Analysis(['setup.py'],	# 此列表填入项目所有python脚本文件
             pathex=['E:\\pyCharmProjects\\Demo'], # 此列表填入项目绝对路径
             binaries=[],
             datas=[],		# 此列表填入所有资源文件路径,每个文件是一个2元组元素,格式为:(文件的源路径, 在打包文件中的路径)
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)

exe = EXE(pyz,
          a.scripts,
    	  [],
	      exclude_binaries=True,
          name='Demo_setup',		   # 生成的 exe 文件的名字
          debug=False,					
          bootloader_ignore_signals=False,
          strip=False,    		# 是否移除所有的符号信息,使打包出的 exe 文件更小
          upx=True,       		# 是否用 upx 压缩 exe 文件
          console=False,		# 此处console=True表示,打包后的可执行文件双击运行时屏幕会出现一个cmd窗口,不影响原程序运行
          disable_windowed_traceback=False,
          argv_emulation=False,
          target_arch=None,
          codesign_identity=None,
          entitlements_file=None,
          icon='E:\\pyCharmProjects\\Demo\\icon.png',  # 此处是打包图标路径
)	


coll = COLLECT(
    exe,
    a.binaries,
    a.zipfiles,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='Demo_setup', # 最后生成的文件夹的名字
)

Analysis [ ‘E:\pyCharmProjects\python加密\register_machine.py’ , ‘xxx.py’]

datas=[ (‘资源文件的目录’,‘调用的临时资源文件目录’),() ]

datas=[('c:\lusers\\Linsh\\Desktop\\Demo_tmpll多文件封装''多文件封装')]
datas=[('res''resource')]
# 如本身被调用的资源就在一个二级文件夹“resoure”里,则修改为“datas=[(‘res’,‘resource’)]”。
datas=[('res''.')]
# 如本身被调用的资源就在当前项目路径下,则用.代替

2.2 修改setup.spec文件

​ 构建自己的 .sepc文件 需要修改Analysis项中的第一个 [](python文件路径) 、pathex值(项目绝对路径)、datas(额外资源路径)、console值(cmd窗口显示)、name值(打包文件名)、icon值(程序图标路径)

优化: 我们创建py_files、add_files两个变量,分别存放python文件路径(相对路径)、资源文件路径,如下图示例

# -*- mode: python ; coding: utf-8 -*-
 
block_cipher = None

# 所有要打包的 python 文件路径
py_files =['appMain.py', 
'myMainWindow.py', 
'myBarSetDlg.py', 
'myDrawBar.py', 
'myDrawScatter.py',
'myQt.py', 
'myRegisterWindow.py', 
'myScatterSetDlg.py', 
'readExcel.py', 
'register.py', 
'ui_File\\myColorButton.py', 
'ui_File\\myFigureCanvas.py', 
'ui_File\\myListWidget.py', 
'ui_File\\myTableView.py', 
'ui_File\\myTable_ColorBtn.py', 
'ui_File\\myTreeWidget.py', 
'ui_File\\resource\\barSettingDlg_ui.py', 
'ui_File\\resource\\drawSettingDlg_ui.py', 
'ui_File\\resource\\mainWindow_ui.py', 
'ui_File\\resource\\register_ui.py', 
'ui_File\\resource\\sheetSelectDlg_ui.py',
]
# 所有要打包的 额外资源文件列表
add_files = [
    ('ui_File\\resource\\images\\img_data.png', 'ui_File\\resource\\images'),
    ('ui_File\\resource\\images\\img_draw.png', 'ui_File\\resource\\images'),
    ('ui_File\\resource\\images\\img_scale.png', 'ui_File\\resource\\images'),
    ('ui_File\\resource\\images\\icon.png', 'ui_File\\resource\\images'),
    ('ui_File\\resource\\myPltStyle.mplstyle', 'ui_File\\resource'),
]


a = Analysis(
    		 py_files,	# 此列表填入项目所有python脚本文件
             pathex=['E:\\pyCharmProjects\\Demo'], # 此列表填入项目绝对路径
             binaries=[],
             datas=add_files,		# 此列表填入所有资源文件路径,每个文件是一个2元组元素,格式为:(文件的源路径, 在打包文件中的路径)
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)

exe = EXE(pyz,
          a.scripts,
    	  [],
	      exclude_binaries=True,
          name='Demo_setup',		   # 生成的 exe 文件的名字
          debug=False,					
          bootloader_ignore_signals=False,
          strip=False,    		# 是否移除所有的符号信息,使打包出的 exe 文件更小
          upx=True,       		# 是否用 upx 压缩 exe 文件
          console=False,		# 此处console=True表示,打包后的可执行文件双击运行时屏幕会出现一个cmd窗口,不影响原程序运行
          disable_windowed_traceback=False,
          argv_emulation=False,
          target_arch=None,
          codesign_identity=None,
          entitlements_file=None,
          icon='E:\\pyCharmProjects\\Demo\\icon.png',  # 此处是打包图标路径
)	


coll = COLLECT(
    exe,
    a.binaries,
    a.zipfiles,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='Demo_setup', # 最后生成的文件夹的名字
)

2.3 UPX压缩

(1)下载安装UPX程序

链接:https://pan.baidu.com/s/1B2fE6R9vDBhKb9Q9FH4VVA?pwd=hpcx

(2)UPX压缩打包

–upx-dir : 输入安装UPX的文件夹目录"D:\xxx\UPX"

  • pyinstaller 参数打包

    #先在源代码和图片的文件夹里打开PowerShell,再用这行命令
    pyinstaller --upx-dir "D:\xxx\UPX" -F "apply.py" --add-data "lemon.gif;." -i "lemon.ico" -w --clean
    #--clean用于清除Pyinstaller的缓存
    
  • UPX 压缩构建好的 .spec 文件

    # 压缩打包构建好.spec文件
    
    pyinstaller --upx-dir "D:\xxx\UPX" xxxx.spec
    

直接使用参数,输入upx的exe的安装路径:pyinstaller --upx-dir "D:\xxx\UPX" xxxx.spec

2.4 总结

使用.spec文件 + UPX压缩打包pyqt项目,使用-w参数生成文件夹。(项目较大加入-w参数,生成文件夹,项目较小使用-F参数,只生成一个单独的可执行文件)

pyinstaller --upx-dir "D:\xxx\UPX" -w setup.spec

.spec文件介绍

# -*- mode: python ; coding: utf-8 -*-


block_cipher = None

# 这一部分负责收集你的脚本需要的所有模块和文件。的;hiddenimports 参数可以指定一些 PyInstaller 无法自动检测到的模块。
a = Analysis(
    ['setup.py'],       # 写入要打包的所有 Python 文件的路径(可以是相对路径)
    pathex=[],          # 写入项目的绝对路径
    binaries=[],        # 包含了动态链接库或共享对象文件,会在运行之后自动更新,加入依赖的二进制文件
    datas=[],           # 列表,存放所有额外资源文件。每个元素都是一个元组,格式为:(文件的源路径, 在打包文件中的路径)
    hiddenimports=[],   # 用于指定一些 PyInstaller 无法自动检测到的模块
    hookspath=[],       # 指定查找 PyInstaller 钩子的路径
    hooksconfig={},     # 自定义 hook 配置,这是一个字典,一行注释写不下,此处先不讲
    runtime_hooks=[],   # 指定运行时 hook,本质是一个 Python 脚本,hook 会在你的脚本运行前运行,可用于准备环境
    excludes=[],        # 用于指定需要排除的模块
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)

# 除此之外,a 还有一些没有列出的属性:
#   pure 是一个列表,包含了所有纯 Python 模块的信息,每个元素是一个元组,包含了:模块名, pyc路径, py 路径,这些模块会被打包到一个 .pyz 文件中。
#   scripts 是一个列表,包含了你的 Python 脚本的信息。每个元素是一个元组,其中包含了脚本的内部名,脚本的源路径,以及一些元数据。这些脚本会被打包到一个可执行文件中。


# pyz 是指生成的可执行文件的名称。它是由 PyInstaller 用来打包 Python 程序和依赖项的主要文件。


# 创建 pyz 文件,它在运行时会被解压缩到临时目录中,然后被加载和执行。它会被打包进 exe 文件
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)


# 创建 exe 文件
exe = EXE(
    pyz,            # 包含了所有纯 Python 模块
    a.scripts,      # 包含了主脚本及其依赖
    [],             # 所有需要打包到 exe 文件内的二进制文件
    exclude_binaries=True,  # 若为 True,所有的二进制文件将被排除在 exe 之外,转而被 COLLECT 函数收集
    name='hello',   # 生成的 exe 文件的名字。
    debug=False,    # 打包过程中是否打印调试信息?
    bootloader_ignore_signals=False,
    strip=False,    # 是否移除所有的符号信息,使打包出的 exe 文件更小
    upx=True,       # 是否用 upx 压缩 exe 文件
    console=True,   # 若为 True 则在控制台窗口中运行,否则作为后台进程运行
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)


# 这个对象包含了所有需要分发的文件
# 包括 EXE 函数创建的 exe 文件、所有的二进制文件、zip 文件(如果有的话)和数据文件
coll = COLLECT(
    exe,
    a.binaries,
    a.zipfiles,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='hello',   # 生成的文件夹的名字
)

三、常见问题:

3.1 报错问题

问题描述:当程序代码出错时,程序会出现闪退,而用户并不知道是什么原因造成的

解决:(1)在程序中使用 try catch 语句抛出

​ (2)在cmd终端下,直接将 .exe所在路径一并输入,在CMD窗口中执行->会在终端输出错误原因

3.2 路径问题

打包好的程序,执行中遇到项目中包含有读取文件的操作,当时用os模块读取到绝对路径时的情况,会出错。

(1)打包时不使用 -F 打包为多个文件的程序,不会出错!

(2)打包时使用 -F 打包为单个文件时,**会报错!**因为 打包为单个文件执行原理是:程序会加载成为进程被临时存储在系统的某个目录下,而此目录下并没有载入程序中需要读取的文件。

  • 解决1: 使用sys.argv:获取当前程序的所在目录列表。
    • 在开发过程中代表当前.py文件所在目录
    • 在打包为 单个 .exe 文件时,就代表当前 .exe 程序执行时 进程临时文件所在的目录
    • 项目的文件需要与 .exe 程序在同一个目录下
import sys
sys.argv    # 返回当前运行文件所在目录列表
sys.argv[0] # 返回当前运行文件的列表的第0个位置元素——当前目录
111

|–ui_file

​ |–read_file.py

|–main.py

# main.py中调用了reda_file.py中的方法
在read_file.py中执行了路径获取
sys.argv[0] 	# 返回调用者-main.py的路径
os.path.dirname(os.path.abspath(__file__))  # 当前文件所在的目录

综上所述:

# 使用如下语句,获取调用者位置的路径
curPath = os.path.dirname(sys.argv[0])
xxpath = os.path.join(curPath,"xxxx")
  • 解决2: 使用 sys.argv:获取当前程序的所在目录列表。

    333
import sys
if getattr(sys,'frozen',False):
    print('运行的是pyinstall打包的程序')
    BASE_BIR=os.path.dirname(sys.executable)
else:
    print('运行的是标准python程序')
  BASE_BIR=os.path.dirname(os.path.abspath(__file__))
'''
解释:在sys中找frozen字段
	如果找到执行else——代表正在执行的是Python程序
	如果没找到则就是False,代表是pyinstall
'''

附:pyinstaller参数详解

pyinstaller -F xxx.py(会出现console窗口)
pyinstaller -F -w xxx.py(不会出现consoe窗口)
pyinstaller -F xxx.pyw(不会出现console窗口)
pyinstaller -i xxx.ico xxx.py(设置.ico图标)pyinstaller -n 牛逼 xxx.py(设置程序名称)
参数参数描述
-F
–onefile
打包单个文件,产生一个.exe执行文件(项目有多个文件时不要使用)
例:pyinstaller -F xxx.pypyinstaller --onefile xxxx.py
-D
–onedir
打包多个文件,产生一个dist目录,用于框架编写的代码打包
例:pyinstaller -D xxx.py(项目入口文件)pyinstaller --onedir xxx.py(项目入口文件)
–upx-dir UPX_DIR用UPX压缩安装
例: pyinstaller --upx-dir "C:\Users\Desktop\upx-4.1.0-win64" xxxx.spec
-p dir
–path=dir
1.使用多个-p参数来设置多个文件导入路径(和使用pythonpath效果相似)
2.可以用路径分割符(Windows使用分号,Linux使用冒号)分割,指定多个目录
-w
–windowed
–noconsole
1.表示去掉控制台窗口,当程序启动的时候不会打开命令行(只对Windows有效)
例:pyinstaller -w xxx.py 或者 pyinstaller xxx.py --noconsole
-c
–nowindowed
–console
1.表示打开控制台窗口,使用控制台子系统执行,当程序启动的时候会打开命令行(默认)(只对Windows有效) 例:pyinstaller -c xxx.py 例:pyinstaller xxx.py --console
-i
--icon=<file.ioc>
程序的图标 (只对Windows系统有效)
例:pyinstaller -F -i file.ico xxx.py 或者 pyinstall -F --icon=<file.ioc> xxx.py
-n name
–name=name
打包程序名
例:pyinstaller -F -n my_file_name xxx.py 或者 pyinstaller -F --name=my_file_name xxx.py
-o dir
– out=dir
1.指定spec文件的生成目录dir 2.如果没有指定则会输出到当前的目录下
–key=keys使用keys进行加密打包
例:pyinstaller --key=1234 -F xx.py
-K
–tk
在部署时包含 TCL/TK
-a
–ascii
不包含编码.在支持 Unicode 的 python 版本上默认包含所有的编码
-d
–debug
产生debug版本的可执行文件
-v file
–version=file
将verfile作为可执行文件的版本资源(只对Windows系统有效)
-s
–strip
可执行文件和共享库将run through strip。注意Cygwin的strip往往使普通的win32 Dll无法使用
  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值