Python使用pickle存二进制用户数据时如何修改指定字段不覆盖全文件
问题解决说明
核心错误点
- 存储逻辑错误:原
create_user函数用追加模式(ab)每次写入独立的pickle序列化列表,导致文件中存在多段序列化数据,读取时只能获取到第一条序列化内容,后续用户数据无法正常加载 - 重置密码逻辑混乱:遍历用户数据的循环内提前关闭文件、未完成全量用户校验就直接覆写文件、数据格式转换逻辑错误、使用
eval执行字符串存在安全隐患 - 数据结构不统一:写入时存的是字符串列表,读取后强行转字典会抛出格式错误,导致更新失败
修正后实现代码
统一调整存储逻辑:所有用户数据统一以字典格式序列化存储,键为用户名(生日拼接的整数),值为包含名、姓、密码的子字典,读写均全量操作,避免多段序列化的兼容性问题。
import pickle def create_user(): # 创建新用户 # 读取已有用户数据,文件不存在则初始化空字典 try: with open("uandp", "rb") as f: users = pickle.load(f) except (FileNotFoundError, EOFError): users = {} # 收集用户输入 birthday = input("请输入出生日期 (格式DD/MM/YYYY): ") day, month, year = birthday.split("/") username = int(f"{day}{month}{year}") # 校验用户名是否重复 if username in users: print("该用户名(生日)已被注册!") return password = int(input("请输入密码: ")) first_name = input("请输入名字: ") last_name = input("请输入姓氏: ") # 写入新用户 users[username] = { "first_name": first_name, "last_name": last_name, "password": password } # 全量覆写文件 with open("uandp", "wb") as f: pickle.dump(users, f) print(f"用户已添加: {first_name} {last_name}")
def reset_password(): # 重置密码 # 读取全量用户数据 try: with open('uandp', 'rb') as f: users = pickle.load(f) except (FileNotFoundError, EOFError): print("无用户数据,请先注册用户!") return # 收集输入 user_name0 = int(input("请输入用户名: ")) # 校验用户是否存在 if user_name0 not in users: print("未找到对应用户!") return new_password = int(input("请输入新密码(最多10位): ")) confirm_new_password = int(input("请再次输入新密码: ")) # 校验密码合法性 if new_password != confirm_new_password: print("两次输入的密码不一致!") return if len(str(new_password)) > 10: print("密码长度不能超过10位!") return # 更新密码并写回文件 users[user_name0]["password"] = new_password with open('uandp', 'wb') as f: pickle.dump(users, f) print("密码修改成功!")
注意事项
- 上述代码仅修复功能逻辑,实际生产环境不要直接明文存储密码,需加密后再写入文件
- pickle序列化生成的是二进制文件,不需要使用txt作为后缀
- 禁止使用
eval执行用户输入内容,会导致严重的代码注入安全问题
内容的提问来源于stack exchange,提问作者Thevedi
相关产品推荐
相关产品推荐

