完整打包脚本解析
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"
作用:定义生成的可执行文件名称
最佳实践:
- 包含应用名称和版本号(如
工具名-v1.0.0
) - 使用下划线代替空格(避免路径问题)
- 示例优化:
app_name = f"微信视频号采集工具_v{version}"
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 有时无法自动检测动态导入的模块
查找缺失模块:
- 打包后运行 exe 文件
- 查看报错信息中缺失的模块
- 添加到 hidden-import 列表
自动化方案:
hidden_imports = ["pandas", "openpyxl", "其他模块"] for module in hidden_imports: pyinstaller_args.append(f"--hidden-import={module}")
高级功能扩展
1. 添加应用图标
# 在参数列表中添加 "--icon=app_icon.ico",
准备图标:
- 使用在线工具将 png 转为 ico 格式
- 推荐尺寸:256x256 像素
注意事项:
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",
常用可排除模块:
- 测试框架:
pytest
,unittest
- 未使用的库:
numpy
,scipy
(如果未使用) - gui 库:
tkinter
,pyqt5
(如果未使用)
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. 缺少依赖模块
解决方案:
- 在打包脚本中添加
--hidden-import=缺失模块
- 检查是否有动态导入(如
__import__()
或importlib
) - 使用
pyi-archive_viewer
分析打包内容
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. 防病毒软件误报
解决方案:
- 使用最新版 pyinstaller(减少误报)
- 对可执行文件进行数字签名
- 在下载页面添加说明,让用户信任文件
打包最佳实践
版本自动化:
# 从代码中获取版本号 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打包脚本内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论