Python打包之嵌入式打包神器PyStand

在使用Python开发项目时,如果项目依赖了如torch这样的大型第三方库,打包后的体积可能会变得非常庞大(超过1GB)。传统的打包工具,如Nuitka或PyInstaller,可能会面临打包成功率低、耗时长、打包后体积巨大的问题。

        为了解决这一问题,龙哥试了几种打包方法,各有好处。本文将探讨一种嵌入式打包的方法,即只分发解释器和核心代码,而第三方依赖则在用户第一次使用程序时现场安装。

解决思路

        通过嵌入式打包,我们可以显著减少分发包的大小。用户在第一次运行程序时,程序会自动安装所需的第三方依赖。这种方法不仅减少了分发包的体积,也避免了传统打包方式可能出现的漏包问题。

示例代码

        本文使用的软件版本为Python 3.10.9。如果你对嵌入式打包不太了解,可以先阅读相关的文章。以下是一个简单的示例项目结构和代码。

项目结构

 

app.py入口文件

from app.main import main
if __name__=="__main__":
    main()

打包准备

  1. 准备项目依赖:在项目环境中运行pip freeze > requirements.txt来导出依赖文件。
  2. 准备嵌入式解释器:可以直接从python官方网站下载。
  3. 准备PyStand壳:从GitHub下载PyStand。
  4. 准备get-pip.py:用于下载pip工具,可以从bootstrap.pypa.io/get-pip.py获取。

开始打包

  • 将代码复制到PyStand同级目录的app文件夹中,并将main.py的内容复制到PyStand的pystand.int文件中,文件重命名_pystand_static.int。
  • runtime文件夹内新建download.py文件,用于在首次运行时安装依赖。 
import os
import sys
from pathlib import Path
 
print("第一次启动,缺少环境依赖,开始安装依赖,请保持网络畅通")
python_path = Path(sys.exec_prefix).joinpath("python.exe")
get_pip_script = Path(sys.exec_prefix).joinpath("get-pip.py")
command = f"{python_path} {get_pip_script}"  # 安装pip工具
os.system(command)
requirements_path = Path(sys.exec_prefix).joinpath("requirements.txt")  # 安装其他依赖
# 安装依赖,这是阿里源
command = str(
    python_path) + " -m pip install --no-warn-script-location -i https://mirrors.aliyun.com/pypi/simple/ -r" + f"{requirements_path}"
status_code = os.system(command)
# 然后退出程序,提醒用户重启
if status_code != 0:
    input("依赖安装失败")
else:
    input("依赖安装完成,请重新打开程序,按回车键退出")
sys.exit()

  • 修改pystand.int文件,捕获ModuleNotFoundError错误,并调用runtime文件夹中的Python解释器运行download.py脚本。

import os
import sys
 
try:
    from app.main import main
except ModuleNotFoundError:
    from pathlib import Path
 
    python_path = Path(sys.exec_prefix).joinpath("python.exe")
    download_script = Path(sys.exec_prefix).joinpath("download.py")
    command = f"{python_path} {download_script}"
    os.system(command)
    sys.exit()

if __name__=="__main__":
    main()
  • requirements.txt文件放置在runtime文件夹中。
  • 修改runtime文件夹中的._pth文件,取消import site前的注释。同时加入项目包目录../app
  • 删除PyStand同级目录的sitepackage文件夹。

最后目录如下。pystand.exe 可以任意修改名字

测试

  1. 双击PyStand,程序会提示缺少依赖并开始安装。
  2. 安装完成后,提示用户重启程序。
  3. 重新双击PyStand,程序将正常启动。

        这样就完美实现小体积分发。打包难度也降低不少。听方便的,至于代码加密,可以用以下几种方法

  1. pyarmor直接加密项目包替换app目录
  2. nuitka 好像把py可以转成pyd,具体没操作
  3. 大家有什么更好的方法可以评论区放出来交流学习一下

最后运行,完美显示。随便写的一个游戏小工具。但是这样其实挺占空间。就这样吧,硬盘反正不值钱了

额外讲解

        这种打包方式利用pip工具让用户在线安装依赖,分发体积小,避免了传统打包方式的缺点。特别适合依赖大型库的项目。用户无需关心本地Python环境,第三方库将被安装在runtime\Lib\site-packages文件夹下。

        对于依赖torch等大型库的项目,可以将依赖文件拆分为两份,分别安装。这样可以确保torch等库的正确安装。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

longm龙哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值