PyInstaller 完整使用教程

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习

🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发

❄️作者主页:一个平凡而乐于分享的小比特的个人主页

✨收录专栏:Python,本专栏为记录项目中用到常用python库

欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

PyInstaller 完整使用教程

一、PyInstaller 简介

PyInstaller 是一个将 Python 程序打包成独立可执行文件的工具,支持 Windows、Linux、macOS 等操作系统。它分析 Python 代码,自动收集所有依赖项(包括隐藏导入),生成单文件或目录结构的可执行程序。

二、安装 PyInstaller

基础安装

bash 复制代码
pip install pyinstaller

升级到最新版本

bash 复制代码
pip install --upgrade pyinstaller

安装开发版本(不推荐生产环境)

bash 复制代码
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip

三、快速开始

最简单的打包命令

bash 复制代码
# 基本打包(生成dist和build目录)
pyinstaller your_script.py

# 打包后会在 dist/your_script 目录中找到可执行文件

创建单文件程序(最常用)

bash 复制代码
pyinstaller --onefile your_script.py
# 生成单个独立的 .exe 文件

创建无控制台窗口的程序(GUI应用)

bash 复制代码
pyinstaller --onefile --windowed your_script.py
# 或
pyinstaller -F -w your_script.py

四、常用命令行参数详解

参数 简写 说明
--onefile -F 打包成单个文件
--onedir -D 打包成目录(默认)
--windowed -w 不显示控制台窗口(GUI程序)
--console -c 显示控制台窗口(默认)
--icon=<图标文件> -i 设置程序图标
--name=<程序名> -n 设置生成的可执行文件名
--clean 清理临时文件
--noupx 不使用 UPX 压缩
--upx-dir=<路径> 指定 UPX 目录
--hidden-import=<模块> 添加隐藏导入的模块
--add-data=<源:目标> 添加数据文件
--add-binary=<源:目标> 添加二进制文件
--paths=<路径> 添加模块搜索路径
--debug 启用调试模式
--strip 剥离符号表(Linux/Mac)

五、实战示例

示例1:基础打包

python 复制代码
# hello.py
import tkinter as tk
from tkinter import messagebox

def show_message():
    messagebox.showinfo("Hello", "欢迎使用PyInstaller!")

if __name__ == "__main__":
    root = tk.Tk()
    root.title("示例程序")
    root.geometry("300x200")
    
    btn = tk.Button(root, text="点击我", command=show_message, font=("Arial", 14))
    btn.pack(expand=True)
    
    root.mainloop()

打包命令:

bash 复制代码
# 打包成单文件GUI程序
pyinstaller --onefile --windowed --icon=myicon.ico --name="MyApp" hello.py

# 打包成目录结构
pyinstaller --onedir --windowed hello.py

示例2:包含数据文件的项目

项目结构:

text 复制代码
my_project/
├── main.py
├── config.json
├── images/
│   └── logo.png
└── data/
    └── database.db
python 复制代码
# main.py
import os
import sys
import json

def resource_path(relative_path):
    """获取资源的绝对路径,支持开发环境和PyInstaller打包后"""
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)

# 读取配置文件
config_path = resource_path('config.json')
with open(config_path, 'r', encoding='utf-8') as f:
    config = json.load(f)

print(f"应用名称: {config['app_name']}")

打包命令:

bash 复制代码
# 添加数据文件和目录
pyinstaller --onefile \
    --add-data="config.json;." \
    --add-data="images/logo.png;images" \
    --add-data="data/database.db;data" \
    main.py

注意 :Windows 使用分号 ; 分隔,Linux/Mac 使用冒号 : 分隔

六、使用 .spec 文件进行高级配置

生成 .spec 文件

bash 复制代码
pyinstaller --onefile your_script.py
# 会自动生成 your_script.spec 文件

手动编辑 .spec 文件示例

python 复制代码
# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

a = Analysis(
    ['main.py'],  # 主程序文件
    pathex=[],    # 额外搜索路径
    binaries=[],  # 二进制文件
    datas=[       # 数据文件
        ('config.json', '.'),
        ('images/*.png', 'images'),
        ('data/*.db', 'data')
    ],
    hiddenimports=[  # 隐藏导入的模块
        'pandas._libs.tslibs.np_datetime',
        'sklearn.utils._weight_vector'
    ],
    hookspath=[],   # 自定义hook路径
    hooksconfig={}, # hooks配置
    runtime_hooks=[], # 运行时hook
    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,
    a.binaries,
    a.zipfiles,
    a.datas,
    [],
    name='MyApplication',  # 程序名
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,  # 使用UPX压缩
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,  # 不显示控制台
    icon='myicon.ico',  # 图标
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

使用 .spec 文件打包

bash 复制代码
# 使用修改后的.spec文件打包
pyinstaller your_script.spec

# 清理后重新打包
pyinstaller --clean your_script.spec

七、处理常见问题

1. 解决隐藏导入问题

bash 复制代码
# 方法1:命令行指定
pyinstaller --onefile --hidden-import=模块名1 --hidden-import=模块名2 your_script.py

# 方法2:创建hook文件
# 在 hooks/ 目录下创建 hook-模块名.py

2. 解决动态导入问题

python 复制代码
# 在代码中显式导入
import importlib

# 动态导入的模块需要在代码开头显式声明
import pandas
import numpy
import sklearn

# 或者在打包时添加
# --hidden-import=pandas --hidden-import=sklearn

3. 路径问题处理

python 复制代码
import os
import sys

def get_resource_path(relative_path):
    """获取资源文件的正确路径"""
    try:
        # PyInstaller创建临时文件夹,将路径存储在_MEIPASS中
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    
    return os.path.join(base_path, relative_path)

# 使用示例
icon_path = get_resource_path('images/icon.ico')

4. 减小可执行文件体积

bash 复制代码
# 使用UPX压缩(需要单独下载UPX)
# 1. 下载UPX: https://upx.github.io/
# 2. 指定UPX路径
pyinstaller --onefile --upx-dir=C:\upx your_script.py

# 排除不需要的模块
pyinstaller --onefile --exclude-module=matplotlib --exclude-module=scipy your_script.py

八、多平台打包

Windows 打包

bash 复制代码
# Windows 专用选项
pyinstaller --onefile --version-file=version.txt your_script.py

# version.txt 示例
VSVersionInfo(
  ffi=FixedFileInfo(
    filevers=(1, 0, 0, 0),
    prodvers=(1, 0, 0, 0),
    mask=0x3f,
    flags=0x0,
    OS=0x40004,
    fileType=0x1,
    subtype=0x0,
    date=(0, 0)
  ),
  kids=[
    StringFileInfo(
      [
        StringTable(
          u'040904B0',
          [StringStruct(u'CompanyName', u'我的公司'),
           StringStruct(u'FileDescription', u'我的应用程序'),
           StringStruct(u'FileVersion', u'1.0.0.0'),
           StringStruct(u'InternalName', u'MyApp'),
           StringStruct(u'LegalCopyright', u'Copyright © 2024'),
           StringStruct(u'OriginalFilename', u'MyApp.exe'),
           StringStruct(u'ProductName', u'我的产品'),
           StringStruct(u'ProductVersion', u'1.0.0.0')])
      ]),
    VarFileInfo([VarStruct(u'Translation', [0x409, 1200])])
  ]
)

Linux 打包

bash 复制代码
# 可能需要安装依赖
sudo apt-get install python3-dev

# 打包命令
pyinstaller --onefile your_script.py

macOS 打包

bash 复制代码
# 打包为.app应用
pyinstaller --windowed --name="MyApp" your_script.py

# 代码签名
pyinstaller --windowed --name="MyApp" \
    --osx-bundle-identifier="com.company.app" \
    your_script.py

九、最佳实践

1. 创建打包脚本

bash 复制代码
# build.bat (Windows)
@echo off
echo 正在清理旧文件...
rmdir /s /q build 2>nul
rmdir /s /q dist 2>nul
del *.spec 2>nul

echo 正在安装依赖...
pip install -r requirements.txt

echo 正在打包...
pyinstaller --onefile --windowed --icon=icon.ico --name="MyApp" main.py

echo 打包完成!程序在 dist 目录中。
pause
bash 复制代码
# build.sh (Linux/Mac)
#!/bin/bash
echo "正在清理旧文件..."
rm -rf build dist *.spec

echo "正在安装依赖..."
pip install -r requirements.txt

echo "正在打包..."
pyinstaller --onefile --windowed --icon=icon.ico --name="MyApp" main.py

echo "打包完成!程序在 dist 目录中。"

2. 创建虚拟环境打包

bash 复制代码
# 创建虚拟环境
python -m venv build_env

# Windows
build_env\Scripts\activate

# Linux/Mac
source build_env/bin/activate

# 安装依赖和PyInstaller
pip install -r requirements.txt
pip install pyinstaller

# 打包
pyinstaller --onefile your_script.py

3. 测试打包结果

bash 复制代码
# 在dist目录中运行
cd dist
./your_script  # Linux/Mac
.\your_script.exe  # Windows

# 检查依赖
# Windows: 使用 Dependency Walker
# Linux: ldd your_script

十、常见错误及解决方案

错误1: ModuleNotFoundError

解决方案

bash 复制代码
# 添加隐藏导入
pyinstaller --hidden-import=missing_module your_script.py

错误2: Failed to execute script

解决方案

bash 复制代码
# 重新打包并显示控制台查看错误
pyinstaller --onefile --console your_script.py

# 或使用调试模式
pyinstaller --debug your_script.py

错误3: 文件体积过大

解决方案

  1. 使用虚拟环境只安装必要包
  2. 使用UPX压缩
  3. 排除不必要的模块

错误4: 杀毒软件误报

解决方案

  1. 对程序进行代码签名
  2. 提交到杀毒软件厂商白名单
  3. 提供源代码证明无害

十一、高级技巧

1. 自定义引导程序

python 复制代码
# 创建 runtime-hooks
# runtime-hooks/myhook.py
import sys
import os

# 在程序启动前执行的代码
sys.stdout = open(os.devnull, 'w')  # 禁用标准输出
bash 复制代码
pyinstaller --runtime-hook=runtime-hooks/myhook.py your_script.py

2. 打包多个脚本

python 复制代码
# multi.spec
exe1 = EXE(pyz, ...)
exe2 = EXE(pyz, ...)

coll = COLLECT(exe1, exe2, ...)

3. 使用配置文件

python 复制代码
# config.py
APP_NAME = "MyApp"
VERSION = "1.0.0"
ICON_PATH = "resources/icon.ico"
bash 复制代码
# build_config.py
import config
import subprocess

cmd = [
    'pyinstaller',
    '--onefile',
    '--windowed',
    f'--name={config.APP_NAME}',
    f'--icon={config.ICON_PATH}',
    'main.py'
]

subprocess.run(cmd)

总结

PyInstaller 是一个强大且灵活的工具,通过本教程你应该能够:

  1. ✅ 掌握基本打包命令
  2. ✅ 处理复杂的依赖关系
  3. ✅ 包含数据文件和资源
  4. ✅ 解决常见的打包问题
  5. ✅ 进行多平台打包

记住,最佳的学习方式是多实践,遇到问题时:

  1. 仔细阅读错误信息
  2. 使用 --debug 模式
  3. 查看官方文档:https://pyinstaller.org/
  4. 搜索 GitHub Issues
相关推荐
‖醉生梦死1 个月前
python程序封装成exe文件
pyinstaller
感谢地心引力2 个月前
【Python】基于 PyQt6 和 Conda 的 PyInstaller 打包工具
数据库·python·conda·pyqt·pyinstaller
小草cys3 个月前
【最佳实践】py文件需要调用exe文件和dll文件,如何打包成exe文件
windows·集成·pyinstaller·py·代码打包
shizidushu3 个月前
使用 Pyinstaller 打包 PPOCRLabel
python·pyinstaller
Just_Paranoid3 个月前
【Python Tkinter】图形用户界面(GUI)开发及打包EXE指南
python·gui·tkinter·pyinstaller
OOQ5 个月前
python制作的软件工具安装包
python·pyinstaller
codefan※10 个月前
在anaconda环境中构建flask项目的exe文件
python·flask·anaconda·pyinstaller·打包部署
大福是小强1 年前
pyinstaller冻结打包多进程程序的bug:无限创建进程直至系统崩溃
bug·pyinstaller·exe·打包·多进程·冻结程序·重复创建进程
不喜欢吃猫的鱼1 年前
streamlit+wordcloud使用pyinstaller打包遇到的一些坑
python·学习方法·pyinstaller·streamlit·wordcloud