深入解析:PyInstaller 完整使用教程

深入解析:PyInstaller 完整使用教程

作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:Python,本专栏为记录项目中用到常用python库 欢迎大家点赞 收藏 ⭐ 加关注哦!

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

二、安装 PyInstaller基础安装

pip install pyinstaller

升级到最新版本

pip install --upgrade pyinstaller

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

pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip

三、快速开始最简单的打包命令

# 基本打包(生成dist和build目录)

pyinstaller your_script.py

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

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

pyinstaller --onefile your_script.py

# 生成单个独立的 .exe 文件

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

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:基础打包

# 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()

打包命令:

# 打包成单文件GUI程序

pyinstaller --onefile --windowed --icon=myicon.ico --name="MyApp" hello.py

# 打包成目录结构

pyinstaller --onedir --windowed hello.py

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

my_project/

├── main.py

├── config.json

├── images/

│ └── logo.png

└── data/

└── database.db

# 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']}")

打包命令:

# 添加数据文件和目录

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 文件

pyinstaller --onefile your_script.py

# 会自动生成 your_script.spec 文件

手动编辑 .spec 文件示例

# -*- 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 文件打包

# 使用修改后的.spec文件打包

pyinstaller your_script.spec

# 清理后重新打包

pyinstaller --clean your_script.spec

七、处理常见问题1. 解决隐藏导入问题

# 方法1:命令行指定

pyinstaller --onefile --hidden-import=模块名1 --hidden-import=模块名2 your_script.py

# 方法2:创建hook文件

# 在 hooks/ 目录下创建 hook-模块名.py

2. 解决动态导入问题

# 在代码中显式导入

import importlib

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

import pandas

import numpy

import sklearn

# 或者在打包时添加

# --hidden-import=pandas --hidden-import=sklearn

3. 路径问题处理

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. 减小可执行文件体积

# 使用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 打包

# 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 打包

# 可能需要安装依赖

sudo apt-get install python3-dev

# 打包命令

pyinstaller --onefile your_script.py

macOS 打包

# 打包为.app应用

pyinstaller --windowed --name="MyApp" your_script.py

# 代码签名

pyinstaller --windowed --name="MyApp" \

--osx-bundle-identifier="com.company.app" \

your_script.py

九、最佳实践1. 创建打包脚本

# 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

# 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. 创建虚拟环境打包

# 创建虚拟环境

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. 测试打包结果

# 在dist目录中运行

cd dist

./your_script # Linux/Mac

.\your_script.exe # Windows

# 检查依赖

# Windows: 使用 Dependency Walker

# Linux: ldd your_script

十、常见错误及解决方案错误1: ModuleNotFoundError解决方案:

# 添加隐藏导入

pyinstaller --hidden-import=missing_module your_script.py

错误2: Failed to execute script解决方案:

# 重新打包并显示控制台查看错误

pyinstaller --onefile --console your_script.py

# 或使用调试模式

pyinstaller --debug your_script.py

错误3: 文件体积过大解决方案:

使用虚拟环境只安装必要包使用UPX压缩排除不必要的模块错误4: 杀毒软件误报解决方案:

对程序进行代码签名提交到杀毒软件厂商白名单提供源代码证明无害十一、高级技巧1. 自定义引导程序

# 创建 runtime-hooks

# runtime-hooks/myhook.py

import sys

import os

# 在程序启动前执行的代码

sys.stdout = open(os.devnull, 'w') # 禁用标准输出

pyinstaller --runtime-hook=runtime-hooks/myhook.py your_script.py

2. 打包多个脚本

# multi.spec

exe1 = EXE(pyz, ...)

exe2 = EXE(pyz, ...)

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

3. 使用配置文件

# config.py

APP_NAME = "MyApp"

VERSION = "1.0.0"

ICON_PATH = "resources/icon.ico"

# 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