国际访客建议访问 Primers 编程伙伴 国际版站点 > Python 教程 > 数据持久化 以获得更好的体验。

# Python 的数据持久化

程序中的数据都保存在内存中,如果希望程序退出后,下次运行时仍能使用之前的数据,就需要对数据进行 持久化,也就是将数据保存到持久性存储器(通常是硬盘)中。

例如如下数据,是游戏中角色的名字、最大血量、当前血量:

player_state:dict = {
    'name': 'link',
    'max_hp': 10,
    'current_hp': 7,
}

玩家退出游戏时,需要将该数据保存到硬盘上,我们无法轻易地将数据直接写入硬盘,通常需要将对象转换为 strbytes 后再进行写入。

相应的,在下一次启动游戏时,我们需要读取数据后转换回原来的 dict

将数据转换为 strbytes 的过程称作 序列化编码,反之责备称作 反序列化解码

示例:

这个示例非常危险,仅作为逻辑演示,不要在实际开发中使用这种方式。

运行示例

# 数据
player_state:dict = {
    'name': 'link',
    'max_hp': 10,
    'current_hp': 7,
}

# 通过 str 函数转换为字符串后写入文件保存
with open("save.data", "w", encoding="utf-8") as fp:
    fp.write(str(player_state))     # str 函数对复杂对象的转换不一定符合预期,请勿用作序列化

# ...

# 下次启动,读取文件
with open("save.data", "r", encoding="utf-8") as fp:
    data = fp.read()

# 转换回 dict
backup_state = eval(data)           # eval 可以执行任何代码,非常危险,请勿用于反序列化

# 查看数据
print(backup_state)

# Python 的对象序列化

Python 中,可以使用内置的 pickle 模块保存和加载对象,dump 函数将对象编码为 bytes 并存入文件,load 函数读取文件并解码为对象。

函数 说明
dumps 将对象编码为 bytes
loads 将 byes 解码为对象
dump 将对象编码为 bytes 并写入文件
laod 读取文件中的 bytes 并解码为对象

函数说明:

def dumps(obj) -> bytes:
    '''
    将对象编码为 bytes

    :param obj: 要保存的对象
    :return: 转换后的 bytes
    '''
    pass

def loads(data:bytes):
    '''
    将 bytes 解码成对象

    :param data: 要解码的 bytes
    :return: 解码出的对象
    '''
    pass

def dump(obj, fp):
    '''
    将对象编码为 bytes 保存到文件中

    :param obj: 要保存的对象
    :param fp: 要写入的文件流
    '''
    pass

def load(fp):
    '''
    读取文件中的 bytes 解码成对象

    :param fp: 要读取的文件流
    :return: 解码出的对象
    '''
    pass

示例:

运行示例

import pickle

# 数据
player_state:dict = {
    'name': 'link',
    'max_hp': 10,
    'current_hp': 7,
}

# 通过 pickle.dump 转换为 bytes 后写入文件保存
with open("save.data", "wb") as fp:
    pickle.dump(player_state, fp)

# ...

# 下次启动,通过 pickle.load 加载数据
with open("save.data", "rb") as fp:
    backup_state = pickle.load(fp)

# 查看数据
print(backup_state)
pickle 仍然不安全,不要加载非受信任源的数据。

pickle 只能用于 Python,并且在 Python 的不同版本之间也存在不兼容的可能性。

实际开发中更常用使用 JSONXML 等标准的结构化数据格式。

本文 更新于: 2025-11-27 09:37:57 创建于: 2025-11-27 09:37:57