Python中Pickle序列化问题:程序退出后数据未保存至文件
解决Python生日程序数据持久化问题
嘿,我明白你的困扰——每次辛辛苦苦添加完好友生日,一关程序就全没了,这确实让人头疼!问题出在你对文件的读写方式上,咱们一步步来修复它:
问题根源分析
你现在用open('birthdays_dict.dat','ab')以追加二进制模式打开文件,这会导致两个核心问题:
- 程序启动时没有从文件加载已保存的生日数据,每次运行都是从头开始的空字典;
- 每次保存都是往文件里追加新的pickle对象,而不是覆盖更新整个字典,后续读取时会因为文件里有多个pickle数据块而报错,或者只能读到最早的那批数据。
修复方案
我们需要做两件关键事:启动时加载已有数据、退出时完整覆盖写入最新数据。这里给你一个完整的修正版本:
import time import pickle def load_birthdays(): """加载已保存的生日数据,文件不存在则返回空字典""" try: with open('birthdays_dict.dat', 'rb') as f: return pickle.load(f) except FileNotFoundError: return {} def save_birthdays(birthdays): """将生日字典完整写入文件,覆盖旧数据""" with open('birthdays_dict.dat', 'wb') as f: pickle.dump(birthdays, f) def add_birthday(birthdays): name = input("请输入好友姓名: ") birthday = input("请输入生日(格式:YYYY-MM-DD): ") birthdays[name] = birthday print(f"已添加 {name} 的生日:{birthday}") def check_todays_birthdays(birthdays): """检查今天的生日并提醒""" today = time.strftime("%m-%d") has_birthday = False print("\n今日生日提醒:") for name, bday in birthdays.items(): if bday.split('-')[1:] == today.split('-'): print(f"🎉 {name} 今天过生日啦!") has_birthday = True if not has_birthday: print("今天没有好友过生日哦~") def main(): # 启动时加载已有数据 birthdays = load_birthdays() while True: print("\n===== 生日管理程序 =====") print("1. 添加生日") print("2. 查看所有生日") print("3. 今日生日提醒") print("4. 退出程序") choice = input("请输入选择(1-4): ") if choice == '1': add_birthday(birthdays) elif choice == '2': print("\n所有好友生日:") for name, bday in birthdays.items(): print(f"{name}: {bday}") elif choice == '3': check_todays_birthdays(birthdays) elif choice == '4': # 退出前保存最新数据 save_birthdays(birthdays) print("数据已保存,再见!") break else: print("无效输入,请重新选择!") if __name__ == "__main__": main()
关键改进点
- 新增
load_birthdays函数:尝试读取文件,文件不存在时返回空字典,确保每次启动都能拿到之前保存的数据; - 用
wb模式(写入二进制)保存数据:每次都会覆盖整个文件,保证文件里只有一个完整的pickle字典对象,读取时不会出错; - 退出程序时才统一保存:避免频繁写入文件,同时确保所有本次会话的修改都被保存;
- 新增了基础的交互功能,让程序更易用。
你可以直接运行这个代码,添加几个生日后退出,再重新启动程序,就能看到之前的数据都还在啦!
内容的提问来源于stack exchange,提问作者Hannah Mishow
相关产品推荐
相关产品推荐

