You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中Pickle序列化问题:程序退出后数据未保存至文件

解决Python生日程序数据持久化问题

嘿,我明白你的困扰——每次辛辛苦苦添加完好友生日,一关程序就全没了,这确实让人头疼!问题出在你对文件的读写方式上,咱们一步步来修复它:

问题根源分析

你现在用open('birthdays_dict.dat','ab')以追加二进制模式打开文件,这会导致两个核心问题:

  1. 程序启动时没有从文件加载已保存的生日数据,每次运行都是从头开始的空字典;
  2. 每次保存都是往文件里追加新的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:23:28