如何使用Python脚本控制PyInstaller打包实战详解!
如何使用Python脚本控制PyInstaller打包实战详解!
作者:一勺菠萝丶
这篇文章将为大家详细介绍如何使用 Python 脚本控制 PyInstaller 打包过程,通过代码注释和功能扩展,让您轻松掌握专业级的应用打包技巧。
完整打包脚本解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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. 程序名称配置
1
|
app_name = "微信视频号数据采集工具v1.0.0" |
作用:定义生成的可执行文件名称
最佳实践:
- 包含应用名称和版本号(如
工具名-v1.0.0
) - 使用下划线代替空格(避免路径问题)
- 示例优化:
app_name = f"微信视频号采集工具_v{version}"
2. 资源文件检查
1
2
|
if not os.path.exists( "README.md" ): # 创建默认说明文件 |
作用:确保必要的文档文件存在
重要性:
- 避免打包过程因缺失文件而中断
- 提供用户友好的使用说明
扩展:可添加多个资源文件检查
1
2
3
4
|
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. 隐藏导入技巧
1
2
|
"--hidden-import=pandas" , "--hidden-import=openpyxl" , |
为什么需要:PyInstaller 有时无法自动检测动态导入的模块
查找缺失模块:
- 打包后运行 exe 文件
- 查看报错信息中缺失的模块
- 添加到 hidden-import 列表
自动化方案:
1
2
3
|
hidden_imports = [ "pandas" , "openpyxl" , "其他模块" ] for module in hidden_imports: pyinstaller_args.append(f "--hidden-import={module}" ) |
高级功能扩展
1. 添加应用图标
1
2
|
# 在参数列表中添加 "--icon=app_icon.ico" , |
准备图标:
- 使用在线工具将 PNG 转为 ICO 格式
- 推荐尺寸:256x256 像素
注意事项:
1
2
3
4
|
if os.path.exists( "app_icon.ico" ): pyinstaller_args.append( "--icon=app_icon.ico" ) else : print ( "警告: 图标文件不存在,使用默认图标" ) |
2. 版本信息管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 创建 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. 排除不必要的模块
1
2
3
|
# 减小可执行文件体积 "--exclude-module=tkinter" , "--exclude-module=matplotlib" , |
常用可排除模块:
- 测试框架:
pytest
,unittest
- 未使用的库:
numpy
,scipy
(如果未使用) - GUI 库:
tkinter
,PyQt5
(如果未使用)
4. 增加文件加密
1
2
|
# 安装所需依赖: pip install pyinstaller[encryption] "--key=my_secret_key" , |
作用:保护 Python 源代码不被轻易反编译
注意事项:
- 加密会增加打包时间
- 不是绝对安全,但增加破解难度
完整增强版打包脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
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 压缩:
1
|
pyinstaller_args.append( "--upx-dir=path/to/upx" ) |
2. 缺少依赖模块
解决方案:
- 在打包脚本中添加
--hidden-import=缺失模块
- 检查是否有动态导入(如
__import__()
或importlib
) - 使用
pyi-archive_viewer
分析打包内容
3. 资源文件找不到
解决方案:
使用正确格式:--add-data="源文件;目标目录"
在代码中使用兼容路径访问:
1
2
3
4
5
6
7
8
9
10
|
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(减少误报)
- 对可执行文件进行数字签名
- 在下载页面添加说明,让用户信任文件
打包最佳实践
版本自动化:
1
2
3
|
# 从代码中获取版本号 import video_data_collector VERSION = video_data_collector.__version__ |
日志记录:
1
2
3
|
# 在打包脚本中添加日志 import logging logging.basicConfig(filename = 'build.log' , level = logging.INFO) |
多平台支持:
1
2
3
4
5
6
7
|
# 处理不同操作系统的路径分隔符 if sys.platform.startswith( 'win' ): data_separator = ";" else : data_separator = ":" pyinstaller_args.append(f "--add-data=README.md{data_separator}." ) |
自动复制资源文件:
1
2
3
4
|
# 打包完成后自动复制资源文件 import shutil for resource in [ "README.md" , "config.ini" ]: shutil.copy(resource, "dist" ) |
到此这篇关于如何使用Python脚本控制PyInstaller打包实战详解的文章就介绍到这了。
学习资料见知识星球。
以上就是今天要分享的技巧,你学会了吗?若有什么问题,欢迎在下方留言。
快来试试吧,小琥 my21ke007。获取 1000个免费 Excel模板福利!
更多技巧, www.excelbook.cn
欢迎 加入 零售创新 知识星球,知识星球主要以数据分析、报告分享、数据工具讨论为主;
1、价值上万元的专业的PPT报告模板。
2、专业案例分析和解读笔记。
3、实用的Excel、Word、PPT技巧。
4、VIP讨论群,共享资源。
5、优惠的会员商品。
6、一次付费只需129元,即可下载本站文章涉及的文件和软件。