python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > PyInstaller打包脚本

如何使用Python脚本控制PyInstaller打包实战详解

作者:一勺菠萝丶

这篇文章将为大家详细介绍如何使用 Python 脚本控制 PyInstaller 打包过程,通过代码注释和功能扩展,让您轻松掌握专业级的应用打包技巧

完整打包脚本解析

import os
import PyInstaller.__main__

# 定义程序名称和版本
app_name = "微信视频号数据采集工具v1.0.0"

# 确保README.md存在 - 提供更好的用户体验
if not os.path.exists("README.md"):
    print("警告: README.md文件不存在,将创建一个空文件")
    with open("README.md", "w", encoding="utf-8") as f:
        f.write("# 微信视频号数据采集工具\n\n请参考使用说明。")

# 定义打包参数 - 核心配置部分
pyinstaller_args = [
    "video_data_collector.py",  # 主程序文件
    "--name={}".format(app_name),  # 程序名称
    "--onefile",  # 打包成单个exe文件
    "--console",  # 保留控制台窗口,因为程序需要用户输入
    # "--icon=icon.ico",  # 如果有图标文件,可以取消注释
    "--clean",  # 每次构建前清理临时文件
    "--add-data={}".format("README.md;."),  # 添加使用文档
    # 添加所需的库 - 解决打包后缺失模块的问题
    "--hidden-import=pandas",
    "--hidden-import=openpyxl",
]

print("开始打包...")
print("这可能需要几分钟时间,请耐心等待...")

# 执行打包命令 - 使用PyInstaller的API接口
PyInstaller.__main__.run(pyinstaller_args)

print("\n打包完成!")
print(f"可执行文件位于 dist/{app_name}.exe")
print("请将README.md文件复制到同一目录,作为使用说明。")

input("按Enter键退出...")

关键参数详解

1. 程序名称配置

app_name = "微信视频号数据采集工具v1.0.0"

作用:定义生成的可执行文件名称

最佳实践

2. 资源文件检查

if not os.path.exists("README.md"):
    # 创建默认说明文件

作用:确保必要的文档文件存在

重要性

扩展:可添加多个资源文件检查

required_files = ["README.md", "config.ini", "icon.ico"]
for file in required_files:
    if not os.path.exists(file):
        # 创建默认文件或警告

3. PyInstaller 核心参数

参数作用示例值注意事项
--onefile生成单个exe文件启动稍慢但分发方便
--console显示控制台窗口调试程序必备,发布时可改为--windowed
--clean清理构建缓存避免旧文件干扰新构建
--add-data添加额外文件"源文件;目标目录"Windows用;,Linux/Mac用:
--hidden-import添加隐藏依赖pandas, openpyxl解决打包后模块缺失问题

4. 隐藏导入技巧

"--hidden-import=pandas",
"--hidden-import=openpyxl",

为什么需要:PyInstaller 有时无法自动检测动态导入的模块

查找缺失模块

自动化方案

hidden_imports = ["pandas", "openpyxl", "其他模块"]
for module in hidden_imports:
    pyinstaller_args.append(f"--hidden-import={module}")

高级功能扩展

1. 添加应用图标

# 在参数列表中添加
"--icon=app_icon.ico",

准备图标

注意事项

if os.path.exists("app_icon.ico"):
    pyinstaller_args.append("--icon=app_icon.ico")
else:
    print("警告: 图标文件不存在,使用默认图标")

2. 版本信息管理

# 创建 version_info.txt 文件
version_info = """
# UTF-8
VSVersionInfo(
  ffi=FixedFileInfo(...),
  kids=[
    StringFileInfo(...),
    VarFileInfo(...)
  ]
)
"""
with open("version_info.txt", "w") as f:
    f.write(version_info)

# 添加到参数
"--version-file=version_info.txt",

作用:在 Windows 属性中显示版本信息

在线生成工具:使用 pyi-grab_version 获取现有 exe 的版本信息模板

3. 排除不必要的模块

# 减小可执行文件体积
"--exclude-module=tkinter",
"--exclude-module=matplotlib",

常用可排除模块

4. 增加文件加密

# 安装所需依赖: pip install pyinstaller[encryption]
"--key=my_secret_key",

作用:保护 Python 源代码不被轻易反编译

注意事项

完整增强版打包脚本

import os
import sys
import PyInstaller.__main__
from datetime import datetime

# 配置信息
APP_NAME = "微信视频号采集工具"
VERSION = "1.0.1"
AUTHOR = "Your Company"
COPYRIGHT = f"Copyright © {datetime.now().year} {AUTHOR}"

# 自动生成带版本号的名称
app_name = f"{APP_NAME}_v{VERSION}"

# 检查必要资源文件
required_resources = {
    "README.md": "# 使用说明\n\n这里是详细的使用指南...",
    "config.ini": "[DEFAULT]\nlang=zh_CN",
    "version_info.txt": f"""# UTF-8
VSVersionInfo(
  ffi=FixedFileInfo(
    filevers=({VERSION.split('.')[0]}, {VERSION.split('.')[1]}, {VERSION.split('.')[2]}, 0),
    prodvers=({VERSION.split('.')[0]}, {VERSION.split('.')[1]}, {VERSION.split('.')[2]}, 0),
    mask=0x3f,
    flags=0x0,
    OS=0x40004,
    fileType=0x1,
    subtype=0x0,
    date=(0, 0)
  ),
  kids=[
    StringFileInfo(
      [
      StringTable(
        '040904B0',
        [StringStruct('CompanyName', '{AUTHOR}'),
         StringStruct('FileDescription', '{APP_NAME}'),
         StringStruct('FileVersion', '{VERSION}'),
         StringStruct('InternalName', '{APP_NAME}'),
         StringStruct('LegalCopyright', '{COPYRIGHT}'),
         StringStruct('OriginalFilename', '{app_name}.exe'),
         StringStruct('ProductName', '{APP_NAME}'),
         StringStruct('ProductVersion', '{VERSION}')])
      ]), 
    VarFileInfo([VarStruct('Translation', [1033, 1200])])
  ]
)"""
}

# 确保资源文件存在
for filename, default_content in required_resources.items():
    if not os.path.exists(filename):
        print(f"创建默认文件: {filename}")
        with open(filename, "w", encoding="utf-8") as f:
            f.write(default_content)

# 构建PyInstaller参数
pyinstaller_args = [
    "video_data_collector.py",  # 主程序
    f"--name={app_name}",       # 程序名称
    "--onefile",                # 单文件模式
    "--console",                # 显示控制台
    "--clean",                  # 清理构建缓存
    "--add-data=README.md;.",   # 添加文档
    "--add-data=config.ini;.",  # 添加配置文件
    "--version-file=version_info.txt",  # 添加版本信息
    # 隐藏导入
    "--hidden-import=pandas",
    "--hidden-import=openpyxl",
    "--hidden-import=requests",
    # 排除模块减小体积
    "--exclude-module=tkinter",
    "--exclude-module=matplotlib",
]

# 添加图标(如果存在)
if os.path.exists("app_icon.ico"):
    pyinstaller_args.append("--icon=app_icon.ico")
else:
    print("警告: 未找到应用图标 (app_icon.ico)")

# 执行打包
print(f"开始打包 {app_name}...")
print("这可能需要几分钟,请耐心等待...")
PyInstaller.__main__.run(pyinstaller_args)

# 打包后处理
dist_path = os.path.join("dist", f"{app_name}.exe")
if os.path.exists(dist_path):
    print(f"\n✅ 打包成功!可执行文件: {dist_path}")
    print("文件大小:", round(os.path.getsize(dist_path)/(1024*1024), 2), "MB")
else:
    print("\n❌ 打包失败,请检查错误信息")

# 资源文件说明
print("\n请将以下文件与可执行文件放在同一目录:")
print("  - README.md   使用说明")
print("  - config.ini  配置文件")

input("\n按 Enter 键退出...")

常见问题解决方案

1. 打包后文件过大

解决方案

使用虚拟环境打包(避免包含不必要的包)

添加排除参数:--exclude-module=未使用的模块

使用 UPX 压缩:

pyinstaller_args.append("--upx-dir=path/to/upx")

2. 缺少依赖模块

解决方案

3. 资源文件找不到

解决方案

使用正确格式:--add-data="源文件;目标目录"

在代码中使用兼容路径访问:

def resource_path(relative_path):
    """ 获取资源的绝对路径 """
    if hasattr(sys, '_MEIPASS'):
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

# 使用示例
readme_path = resource_path("README.md")

4. 防病毒软件误报

解决方案

打包最佳实践

版本自动化

# 从代码中获取版本号
import video_data_collector
VERSION = video_data_collector.__version__

日志记录

# 在打包脚本中添加日志
import logging
logging.basicConfig(filename='build.log', level=logging.INFO)

多平台支持

# 处理不同操作系统的路径分隔符
if sys.platform.startswith('win'):
    data_separator = ";"
else:
    data_separator = ":"

pyinstaller_args.append(f"--add-data=README.md{data_separator}.")

自动复制资源文件

# 打包完成后自动复制资源文件
import shutil
for resource in ["README.md", "config.ini"]:
    shutil.copy(resource, "dist")

到此这篇关于如何使用Python脚本控制PyInstaller打包实战详解的文章就介绍到这了,更多相关PyInstaller打包脚本内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文