Python如何高效存储类实例到文本文件并解决反序列化与换行问题
问题1:实现自定义类实例的持久化存储与读取
你当前直接存储构造函数字符串或者str(实例)的方式都无法直接还原为实例,可选择以下两种方案解决:
- 方案1:基于序列化+base64编码适配文本存储(推荐,兼容性好)
用Python内置的pickle模块序列化实例,再转成base64字符串写入文本,读取时反向操作即可,示例代码:
注意:import pickle, base64 # 写入时的处理 if "MAINWEAPON" not in inv or inv["MAINWEAPON"] == "": # 直接存实例,不要转字符串 inv["MAINWEAPON"] = Weapon(sw, 0, Ability(0, "0"), [f"{name}'s first weapon."], dmg=30, cc=20, str=15) # 序列化字典并转成文本可存储的字符串 ser_inv = base64.b64encode(pickle.dumps(inv)).decode('utf-8') lines[1] = ser_inv + '\n' # 注意换行处理 # 读取时的处理 ser_inv = lines[1].strip() inv = pickle.loads(base64.b64decode(ser_inv)) # 此时inv["MAINWEAPON"]就是Weapon类实例pickle仅可用于读取你自己生成的可信内容,不要加载未知来源的序列化文件。 - 方案2:基于
__repr__+ 实例重建(适合小项目轻量使用)
给Weapon、Ability类实现__repr__方法,返回可直接重建实例的构造代码,示例:
写入时用class Ability: # 原有代码省略 def __repr__(self): return f"Ability({self.param1}, {repr(self.param2)})" # 按你实际的属性调整 class Weapon: # 原有代码省略 def __repr__(self): return f"Weapon({repr(self.sw)}, {self.level}, {repr(self.ability)}, {repr(self.desc)}, dmg={self.dmg}, cc={self.cc}, str={self.str})"repr(inv)代替str(inv),读取时用ast.literal_eval(需提前导入ast模块)还原字典即可。
问题2:文件行数减少的原因与修复
错误原因
readlines()读取到的每一行默认自带换行符\n,你给lines[1]强制拼接\n时,如果原文件的换行符是\r\n(Windows系统)或\r(老Mac系统),默认r模式不会统一识别换行符,可能导致行合并,最终行数减少。- 没有提前判断读取到的
lines长度,如果读文件异常导致lines长度小于2,后续写入会直接丢失末尾行。
修复代码
# 打开文件时指定newline参数统一识别所有换行格式 with open(memorypath(), "r", encoding='utf-8', newline='') as f: lines = f.readlines() inv = inventory() if "MAINWEAPON" not in inv or inv["MAINWEAPON"] == "": inv["MAINWEAPON"] = Weapon(sw, 0, Ability(0, "0"), [f"{name}'s first weapon."], dmg=30, cc=20, str=15) # 先判断lines长度,避免索引越界,再处理换行 ser_inv = base64.b64encode(pickle.dumps(inv)).decode('utf-8') if len(lines) >= 2: # 统一处理换行,保留原行的换行规则,避免额外新增/丢失换行 lines[1] = ser_inv + lines[1][len(lines[1].rstrip('\r\n')):] else: # 行数不足时补空行到至少2行 while len(lines) < 2: lines.append('\n') lines[1] = ser_inv + '\n' # 写入时也指定newline参数,避免换行符自动转换 with open(memorypath(), "w", encoding='utf-8', newline='') as f: f.writelines(lines)
内容的提问来源于stack exchange,提问作者Gamer 13
相关产品推荐
相关产品推荐

