Python类对象序列化/反序列化选json还是pickle?如何实现?
选型建议
优先选择JSON库,理由如下:
- 你的设备属性(字符串、整数、浮点数列表)均为JSON原生支持的类型,适配成本极低
- JSON为纯文本格式,可直接打开查看内容,排查问题更方便
- 无安全风险,跨语言跨平台兼容性好,后续如果要用其他语言读取数据也不需要额外转换
如果后续你的unit_log类会加入Python专属属性(比如函数引用、其他自定义类的嵌套对象),再考虑使用pickle库,pickle可以直接序列化整个类实例,不需要手动做格式转换,但缺点是生成的是二进制文件不可读,仅支持Python环境使用,加载来源不明的pickle文件存在执行恶意代码的安全风险。
完整功能实现(JSON版本)
修改你的file.py代码如下:
import json import os class unit_log: # 类属性:存储所有设备实例 units = {} # 数据存储路径,可自行修改 DATA_FILE = "unit_logs.json" def __init__(self, serial_number): self.serial_number = serial_number self.unit_name = f'unit_{serial_number}' self.status = 'Open' self.offsets = [] self.folder = f'C:\\Users\\Thomas\\Documents\\{serial_number}' # 新建实例自动加入全局存储 unit_log.units[self.unit_name] = self # 同步到模块全局变量,支持直接用unit_1这种方式访问 globals()[self.unit_name] = self @classmethod def load(cls): # 不存在数据文件时直接返回 if not os.path.exists(cls.DATA_FILE): return with open(cls.DATA_FILE, 'r', encoding='utf-8') as f: data = json.load(f) # 清空旧实例避免冲突 cls.units.clear() # 遍历存储数据生成类实例 for unit_data in data.values(): unit = cls(unit_data['serial_number']) # 覆盖默认属性为存储的属性值 unit.status = unit_data['status'] unit.offsets = unit_data['offsets'] unit.folder = unit_data['folder'] @classmethod def save(cls): # 把所有实例转换为可序列化的字典 data = {} for unit_name, unit in cls.units.items(): data[unit_name] = { "unit_name": unit.unit_name, "serial_number": unit.serial_number, "status": unit.status, "offsets": unit.offsets, "folder": unit.folder } # 写入JSON文件 with open(cls.DATA_FILE, 'w', encoding='utf-8') as f: json.dump(data, f, indent=4, ensure_ascii=False)
使用方法
和你要求的操作逻辑完全一致:
- 加载已有数据
from file import unit_log unit_log.load()
- 访问已有设备
print(unit_1.serial_number) # 输出 1
- 修改设备属性
unit_1.status = 'Closed' unit_1.offsets.append(0.02)
- 新增设备
unit_2 = unit_log(2)
- 保存所有修改到文件
unit_log.save()
可选:pickle版本实现(更简洁)
如果你不需要可读的文本格式,pickle版本不需要手动做属性转换,代码更简单:
import pickle import os class unit_log: units = {} DATA_FILE = "unit_logs.pkl" def __init__(self, serial_number): self.serial_number = serial_number self.unit_name = f'unit_{serial_number}' self.status = 'Open' self.offsets = [] self.folder = f'C:\\Users\\Thomas\\Documents\\{serial_number}' unit_log.units[self.unit_name] = self globals()[self.unit_name] = self @classmethod def load(cls): if not os.path.exists(cls.DATA_FILE): return with open(cls.DATA_FILE, 'rb') as f: cls.units = pickle.load(f) # 同步实例到全局变量 for unit_name, unit in cls.units.items(): globals()[unit_name] = unit @classmethod def save(cls): with open(cls.DATA_FILE, 'wb') as f: pickle.dump(cls.units, f)
使用方法和JSON版本完全相同。
内容的提问来源于stack exchange,提问作者Thomas K
相关产品推荐
相关产品推荐

