使用PyInstaller打包Python/Kivy程序时Pickle文件找不到的解决方法
问题
我用PyInstaller打包基于Python+Kivy开发的程序,程序需要读取Pickle格式的保存文件。尝试用--add-data参数将Pickle文件加入打包后,运行生成的可执行文件时总是提示文件不存在;换成--add-binary参数也没有效果。但同样用--add-data添加的JSON文件却能正常读取。
我的构建脚本如下:
python -m PyInstaller --onefile --noconsole --windowed \ --icon="../TOOL/utils/style/EC_APP_ICON.ico" \ --name="EC App" \ --add-data="../TOOL/utils/fonts/Long Today.ttf:utils/fonts/" \ --add-data="../TOOL/utils/fonts/HeyFun.ttf:utils/fonts" \ --add-data="../TOOL/utils/fonts/Copyduck.ttf:utils/fonts" \ --add-data="../TOOL/utils/style/gui.kv:utils/style/" \ --add-data="../TOOL/utils/style/logo.png:utils/style/" \ --add-data="../TOOL/utils/style/ita.png:utils/style" \ --add-data="../TOOL/utils/style/eng.png:utils/style" \ --add-data="../TOOL/utils/style/reset.png:utils/style/" \ --add-data="../TOOL/utils/style/download.png:utils/style" \ --add-data="../TOOL/utils/style/EC_APP_ICON.ico:utils/style" \ --add-data="../TOOL/utils/lang/ita-eng.json:utils/lang/" \ --add-data="../TOOL/utils/lang/eng-ita.json:utils/lang/" \ --add-binary="../TOOL/utils/save/restore.pkl:utils/save/" \ --add-binary="../TOOL/utils/save/dump.pkl:utils/save/" ..\TOOL\tool.py
解决方案
1. 用--add-data统一处理Pickle文件
PyInstaller的--add-binary是给可执行二进制文件准备的,Pickle属于数据文件,应该用--add-data。把脚本里的--add-binary替换成--add-data,同时保持路径格式和其他数据文件一致:
--add-data="../TOOL/utils/save/restore.pkl:utils/save/" \ --add-data="../TOOL/utils/save/dump.pkl:utils/save/"
2. 修复代码中的文件读取路径逻辑
打包后的程序会在临时目录运行,不能直接用相对路径读取文件,必须通过PyInstaller提供的sys._MEIPASS获取临时目录的真实路径。修改代码中读取Pickle文件的部分:
import sys import os import pickle # 获取资源文件的绝对路径 def get_resource_path(relative_path): if hasattr(sys, '_MEIPASS'): return os.path.join(sys._MEIPASS, relative_path) return os.path.join(os.path.abspath("."), relative_path) # 读取Pickle文件的示例代码 restore_file_path = get_resource_path("utils/save/restore.pkl") with open(restore_file_path, 'rb') as f: saved_data = pickle.load(f)
3. 检查路径拼写与格式一致性
确认脚本中--add-data冒号后的目标路径,和代码中读取文件的路径完全一致,比如有没有漏写斜杠、大小写错误(Windows下不敏感,但跨平台需注意)。
4. 验证打包后的文件结构
可以先去掉--onefile参数,生成文件夹形式的程序,查看dist/EC App目录下是否存在utils/save/文件夹,以及里面的Pickle文件是否存在,快速定位是打包时未添加文件,还是读取路径错误。
内容的提问来源于stack exchange,提问作者Manuel Galleani
相关产品推荐
相关产品推荐

