🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习
🎬擅长领域:驱动开发,嵌入式软件开发,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: 文件体积过大
解决方案:
- 使用虚拟环境只安装必要包
- 使用UPX压缩
- 排除不必要的模块
错误4: 杀毒软件误报
解决方案:
- 对程序进行代码签名
- 提交到杀毒软件厂商白名单
- 提供源代码证明无害
十一、高级技巧
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 是一个强大且灵活的工具,通过本教程你应该能够:
- ✅ 掌握基本打包命令
- ✅ 处理复杂的依赖关系
- ✅ 包含数据文件和资源
- ✅ 解决常见的打包问题
- ✅ 进行多平台打包
记住,最佳的学习方式是多实践,遇到问题时:
- 仔细阅读错误信息
- 使用
--debug模式 - 查看官方文档:https://pyinstaller.org/
- 搜索 GitHub Issues