当前位置: 首页 > news >正文

实测对比:PyInstaller vs Nuitka打包后,用这个工具分别能瘦身多少?附Matplotlib/Numpy案例

PyInstaller vs Nuitka 终极瘦身实测:Matplotlib/Numpy 项目体积优化全记录

每次用 Python 写完工具准备分享给同事时,最尴尬的莫过于对方看到几百兆的安装包后那句"这真是个小工具吗?"。上周我用 Matplotlib 做了个简单的数据可视化工具,PyInstaller 打包后居然有 42MB,而同样的功能用 C++ 编译出来可能不到 5MB。这促使我系统性地测试了主流 Python 打包方案及其瘦身技巧,特别是当项目包含科学计算库时的优化空间。

1. 测试环境与基准建立

1.1 实验设计思路

为了获得可比性数据,我设计了一个标准测试用例:一个使用 Numpy 生成随机数据并用 Matplotlib 绘制散点图的脚本。选择这两个库是因为它们:

  • 是数据科学项目的典型依赖
  • 包含大量可能未使用的编译文件和资源
  • 在不同打包工具中的处理方式差异明显

测试环境配置如下:

环境项配置详情
操作系统Windows 11 22H2
Python 版本3.9.13 (Miniconda 环境)
测试库版本Numpy 1.23.5, Matplotlib 3.6.2
打包工具版本PyInstaller 5.7.0, Nuitka 1.4.6

1.2 基准代码实现

# scatter_plot.py import numpy as np import matplotlib.pyplot as plt def generate_plot(): np.random.seed(2023) x = np.random.normal(0, 1, 500) y = np.random.normal(0, 1, 500) plt.style.use('ggplot') fig, ax = plt.subplots(figsize=(8,6)) ax.scatter(x, y, alpha=0.6, c=np.sqrt(x**2 + y**2), cmap='viridis') ax.set_title('Multivariate Normal Distribution', pad=20) ax.set_xlabel('X Value', labelpad=10) ax.set_ylabel('Y Value', labelpad=10) plt.savefig('scatter.png', dpi=120, bbox_inches='tight') plt.close() if __name__ == '__main__': generate_plot() input("Plot generated. Press Enter to exit...")

这段代码特意包含了 Matplotlib 的样式设置和复杂绘图选项,以确保打包时包含完整的库功能。

2. 初始打包体积对比

2.1 PyInstaller 打包结果

使用以下命令进行打包:

pyinstaller --onefile --clean --upx-dir=./upx-3.96-win64 scatter_plot.py

打包结果分析:

文件类型大小 (MB)占比主要构成
原始 EXE42.7100%包含所有依赖的独立可执行文件
解压后文件夹158.2370%运行时临时解压的全部内容
关键子目录
├─matplotlib89.356.4%字体、样式、后端驱动等
├─numpy37.823.9%核心库及扩展模块
└─PIL12.17.6%图像处理相关依赖

2.2 Nuitka 打包结果

使用以下命令进行打包:

nuitka --onefile --remove-output --plugin-enable=numpy --windows-icon-from-ico=icon.ico scatter_plot.py

打包结果对比:

指标PyInstallerNuitka差异
EXE 文件大小42.7MB38.2MB-10.5%
启动时间2.3s1.1s-52.2%
内存占用145MB112MB-22.8%
依赖文件数量327个291个-11.0%

Nuitka 的打包优势主要来自:

  • 更智能的依赖分析
  • C++ 编译优化
  • 动态链接部分系统库

3. 瘦身工具实战应用

3.1 瘦身工具工作原理

我们使用的瘦身工具基于动态分析原理,其工作流程如下:

  1. 运行监控阶段

    • 启动待分析的可执行文件
    • 使用 API Hook 技术记录所有文件访问操作
  2. 依赖分析阶段

    • 生成实际使用的文件清单
    • 对比打包目录中的全部文件
  3. 清理优化阶段

    • 移动未使用的文件到备份目录
    • 生成文件迁移报告
    • 保留原始目录结构

3.2 PyInstaller 瘦身过程

操作步骤:

python shrink_tool.py --target=dist/scatter_plot --log-level=debug

关键日志输出:

[DEBUG] 开始分析目录: dist/scatter_plot [INFO] 检测到 PyInstaller 打包结构 [DEBUG] 监控到已加载模块: numpy.core._multiarray_umath [DEBUG] 监控到资源访问: matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf [WARNING] 未使用文件: matplotlib/backends/_backend_tk.cp39-win_amd64.pyd

瘦身前后对比:

项目瘦身前瘦身后缩减比例
总文件数32718443.7%
文件夹大小158.2MB67.5MB57.3%
运行时内存145MB138MB4.8%

3.3 Nuitka 瘦身效果

针对 Nuitka 的特殊处理:

# Nuitka 专用白名单配置 { "nuitka_specific": [ "*.dist/Microsoft.VC140.CRT/*", "*.dist/python39.dll", "*.dist/zlib.pyd" ], "always_keep": [ "**/site-packages/numpy/core/*.dll", "**/matplotlib/backends/backend_qt5agg.py" ] }

优化结果:

优化阶段文件大小较原始缩减
初始打包38.2MB-
基础瘦身29.7MB22.3%
手动优化后24.1MB36.9%
UPX 压缩后18.4MB51.8%

4. 深度优化技巧

4.1 依赖树修剪技术

通过pipdeptree分析发现可以优化的依赖:

pipdeptree --packages numpy,matplotlib --freeze | grep -v "^\s"

输出显示可以移除的间接依赖:

mkl-service==2.4.0 pyparsing==3.0.9 cycler==0.11.0

优化方法:

# setup.cfg 中添加排除项 [options] install_requires = numpy>=1.21 matplotlib>=3.5 exclude_packages = mkl pyparsing

4.2 资源文件选择性打包

Matplotlib 字体优化方案:

  1. 创建自定义字体清单:

    # font_list.py from matplotlib import font_manager fonts = [f.name for f in font_manager.fontManager.ttflist if f.name in ('DejaVu Sans', 'Arial')] print(f"Required fonts: {fonts}")
  2. 修改打包配置:

    # hook-matplotlib.py datas = [ ('mpl-data/fonts/ttf/DejaVuSans.ttf', 'matplotlib/mpl-data/fonts/ttf'), ('mpl-data/matplotlibrc', 'matplotlib/mpl-data') ]

4.3 二进制文件压缩对比

测试不同压缩工具效果:

工具压缩级别PyInstaller 大小Nuitka 大小耗时
无压缩-42.7MB38.2MB-
UPX--best31.5MB (-26.2%)28.1MB (-26.4%)45s
AspackMax29.8MB (-30.2%)26.4MB (-30.9%)68s
MPRESSUltra28.3MB (-33.7%)25.1MB (-34.3%)52s

注意:过度压缩可能导致杀毒软件误报,建议测试后选择平衡方案

5. 工程实践建议

经过两周的测试和十几次打包迭代,总结出以下实用经验:

  1. 工具选型策略

    • 快速原型开发 → PyInstaller(调试方便)
    • 生产环境发布 → Nuitka(性能更优)
    • 极致体积需求 → PyInstaller + 深度瘦身
  2. 目录结构优化

    dist/ ├── app.exe # 主程序 ├── runtime/ # 动态加载的依赖 │ ├── numpy/ # 科学计算库 │ └── matplotlib/ # 绘图相关 └── data/ # 资源文件
  3. 持续集成配置

    # .github/workflows/build.yml - name: Build with Nuitka run: | nuitka --onefile --include-package-data=matplotlib \ --remove-output --output-dir=dist src/app.py python shrink_tool.py --target=dist/app.dist \ --config=.shrinkrc.json upx --lzma --best dist/app.exe
http://www.jsqmd.com/news/730430/

相关文章:

  • 2026年涂塑钢管服务商哪家靠谱排名 - mypinpai
  • PHP 9.0协程AI机器人突然OOM?揭秘内存泄漏的3个隐藏根源与4种压测验证法(附GDB+Valgrind实操录屏)
  • 低代码平台开发详解
  • 2026涂装废水处理厂家哪家好?技术实力与应用场景解析 - 品牌排行榜
  • NVIDIA Profile Inspector终极指南:5个步骤解锁显卡隐藏性能,告别游戏卡顿
  • Redis 核心数据结构(三)——Hash,把一堆字段塞进一个 Key
  • 避开STC8H PWM输入捕获的那些坑:从寄存器配置到中断处理的避坑指南
  • 金刚砂耐磨材料好用吗?湖南正欧告诉你 - mypinpai
  • 交互式训练框架:实时反馈驱动的机器学习优化
  • “小龙虾”浪潮热:提供 2026年OpenClaw 服务的云厂商一览
  • 2026水果店加盟哪个品牌靠谱?供应链与体验成关键考量 - 品牌排行榜
  • AI辅助现代软件开发方法
  • 告别Modelsim:手把手教你配置PDS与Vivado/QuestaSim进行联合仿真与调试
  • Autovisor:智慧树自动化学习终极指南,如何用Python解放你的学习时间
  • 保姆级教程:在RK3562上搞定OV13855和GC8034双摄切换(附完整DTS配置)
  • G-Helper终极指南:3分钟掌握华硕笔记本性能优化技巧
  • 2026年工业润滑油哪家性价比高 - mypinpai
  • 追觅美国硅谷发布硬核产品,火箭车挑战0.9秒破百
  • Claude-Skills技能库:扩展AI能力边界,构建自动化应用
  • 智慧树网课自动化解决方案:技术实现与效率提升完整指南
  • JetBrains IDE试用期重置终极指南:如何轻松恢复30天免费试用
  • KMS智能激活实战指南:3种高效配置方案
  • SchoolCMS:突破性开源教务管理系统的技术架构深度解析
  • 企业内网系统通过Taotoken安全调用大模型服务的架构设计与实践
  • 自动评分系统的人机分布匹配技术实践
  • 2026中效过滤器哪个品牌好?行业口碑推荐榜 - 品牌排行榜
  • 2026年年度排名:服务响应快的小面调料服务商推荐 - mypinpai
  • Repo、Git、Git-Repo傻傻分不清?一文讲透它们的区别与适用场景
  • 如何10分钟掌握BepInEx:游戏插件框架完整入门指南
  • 电力世界的“备胎”:一文看懂静态UPS的前世今生