如何让PyInstaller打包的exe可存储JSON数据且重启后不丢失?
解决PyInstaller打包后JSON数据重启丢失的问题
问题根源
PyInstaller打包时会把data目录嵌入到exe中,程序运行时会自动将这些文件解压到系统临时目录(比如Windows的%temp%\_MEIxxxxxx)。你运行时写入这个临时目录的JSON文件,在程序关闭后会随着临时目录被自动清理,导致数据丢失。
解决步骤
1. 选择持久化存储路径
放弃使用打包生成的临时data目录,改用固定的、不会被系统清理的路径,推荐以下两种:
- 用户应用数据目录(Windows的
AppData/Roaming、macOS的~/Library/Application Support、Linux的~/.config) - 用户文档目录(比如Windows的
Documents)
这类路径无需管理员权限,且属于用户专属存储区域,不会被随意清理。
2. 修改代码动态生成存储路径
在Python代码中动态获取持久化路径,替换原来的相对路径./data/xxx.json。示例代码如下:
import os import json from pathlib import Path def get_persistent_data_dir(): # 跨平台获取应用专属存储目录 if os.name == 'nt': # Windows系统 data_dir = Path(os.environ['APPDATA']) / "YourAppName" / "data" else: # macOS/Linux系统 data_dir = Path.home() / ".config" / "YourAppName" / "data" # 自动创建不存在的目录 data_dir.mkdir(parents=True, exist_ok=True) return data_dir # 定义JSON数据文件路径 data_file = get_persistent_data_dir() / "saved_data.json" # 保存数据函数 def save_data(data): with open(data_file, 'w', encoding='utf-8') as f: json.dump(data, f, indent=2) # 加载数据函数 def load_data(): if data_file.exists(): with open(data_file, 'r', encoding='utf-8') as f: return json.load(f) return {} # 无数据时返回默认空字典
3. 处理初始默认数据(可选)
如果打包的data目录里有初始默认数据,程序启动时可以检查持久化目录是否存在数据,若不存在则复制默认数据过去:
import sys def get_default_data_path(): # 获取打包后exe内部的默认数据路径 if getattr(sys, 'frozen', False): # 打包后的运行环境,sys._MEIPASS是临时解压目录 base_path = sys._MEIPASS else: # 开发环境下的路径 base_path = os.path.dirname(os.path.abspath(__file__)) return Path(base_path) / "data" / "default_data.json" def init_default_data(): if not data_file.exists(): # 复制默认数据到持久化目录 default_path = get_default_data_path() with open(default_path, 'r', encoding='utf-8') as f: default_data = json.load(f) save_data(default_data) # 程序启动时执行初始化 init_default_data()
4. 调整PyInstaller打包配置
确保spec文件中仍然包含初始data目录,比如在Analysis的datas参数中添加:
a = Analysis( ['your_main_script.py'], datas=[('data', 'data')], # 将本地data目录打包进exe,解压后仍为data目录 # 其他打包配置... )
关键注意事项
- 绝对不要依赖PyInstaller的临时解压目录存储用户数据,该目录仅用于读取打包的静态资源。
- 选择存储路径时优先避开需要管理员权限的目录(比如Windows的
Program Files),避免运行时权限报错。 - 用
pathlib或os.environ处理跨平台路径差异,保证程序在不同系统下都能正常工作。
内容的提问来源于stack exchange,提问作者Mazze
相关产品推荐
相关产品推荐

