程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Python 基础

    • Python基础
  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip包管理工具
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
前端 (opens new window)
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Python 基础

  • Python 进阶

    • 装饰器与生成器
    • 异常处理
    • 标准库精讲
    • 模块与包
    • pip 包管理工具
    • 序列化与反序列化
      • 1. json 模块:通用数据交换格式
        • 1.1 序列化:将 Python 对象转为 JSON 字符串
        • 1.2 反序列化:将 JSON 字符串转为 Python 对象
        • 1.3 直接与文件交互:dump() 和 load()
      • 2. pickle 模块:Python 专用序列化协议
        • 2.1 序列化与反序列化
        • 2.2 直接与文件交互
      • 3. json vs pickle 对比总结
  • Python爬虫

  • Scrapy 爬虫框架

  • Python
  • Python 进阶
scholar
2025-07-24
目录

序列化与反序列化

# Python 序列化与反序列化

在编程中,我们经常需要将程序中的数据结构(如字典、列表、对象等)转换为一种可以被存储或传输的格式,这个过程称为序列化 (Serialization)。反之,将这种格式的数据重新还原为内存中的数据结构,则称为反序列化 (Deserialization)。

为什么需要序列化?

  1. 数据持久化 (Persistence): 将内存中的对象状态保存到文件或数据库中,以便程序下次运行时可以恢复。例如,保存游戏进度、应用程序配置等。
  2. 网络传输 (Communication): 在网络上发送数据时,我们不能直接传输内存中的对象。必须先将其序列化为字节流(如 JSON 字符串),然后在接收端再反序列化。
  3. 跨平台/语言数据交换: 通过一种通用的数据格式(如 JSON 或 XML),让使用不同语言编写的程序能够相互交换数据。

Python 标准库提供了两个核心模块来完成这项工作:json 和 pickle。


# 1. json 模块:通用数据交换格式

JSON (JavaScript Object Notation) 是一种轻量级的、人类易读的数据交换格式。它独立于任何编程语言,已成为事实上的网络数据传输标准。

特点:

  • 通用性强: 几乎所有主流编程语言都有解析 JSON 的库。
  • 可读性好: 纯文本格式,易于人类阅读和编写。
  • 数据类型有限: 只能表示一部分 Python 内建类型。

Python 与 JSON 类型对应关系:

Python JSON
dict object (对象)
list, tuple array (数组)
str string (字符串)
int, float number (数字)
True / False true / false
None null

注意:JSON 不支持 Python 的 set、bytes 或自定义对象等。

# 1.1 序列化:将 Python 对象转为 JSON 字符串

使用 json.dumps() (dump string) 方法。

import json

# 一个包含多种基本数据类型的 Python 字典
data = {
    "name": "小明",
    "age": 25,
    "is_student": True,
    "courses": ["数学", "英语"],
    "address": None
}

# 序列化为 JSON 格式的字符串
# indent=4 参数会让输出的字符串格式化,更易读
# ensure_ascii=False 确保中文字符能被正确显示,而不是被转义为 \uXXXX
json_string = json.dumps(data, indent=4, ensure_ascii=False)

print("--- JSON 字符串 ---")
print(json_string)
print(f"\n类型: {type(json_string)}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

输出:

--- JSON 字符串 ---
{
    "name": "小明",
    "age": 25,
    "is_student": true,
    "courses": [
        "数学",
        "英语"
    ],
    "address": null
}

类型: <class 'str'>
1
2
3
4
5
6
7
8
9
10
11
12
13

# 1.2 反序列化:将 JSON 字符串转为 Python 对象

使用 json.loads() (load string) 方法。

json_string_from_web = """
{
    "user_id": 1001,
    "username": "alice",
    "roles": ["editor", "reviewer"]
}
"""

# 反序列化为 Python 字典
python_dict = json.loads(json_string_from_web)

print("--- Python 字典 ---")
print(python_dict)
print(f"\n类型: {type(python_dict)}")
print(f"用户名: {python_dict['username']}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

输出:

--- Python 字典 ---
{'user_id': 1001, 'username': 'alice', 'roles': ['editor', 'reviewer']}

类型: <class 'dict'>
用户名: alice
1
2
3
4
5

# 1.3 直接与文件交互:dump() 和 load()

当需要将数据直接写入文件或从文件中读取时,使用 json.dump() 和 json.load() 会更方便。

  • json.dump(obj, file_pointer): 将 Python 对象序列化后写入文件。
  • json.load(file_pointer): 从文件中读取 JSON 数据并反序列化。
# 数据
config = {
    "theme": "dark",
    "font_size": 16,
    "plugins": ["spell-check", "auto-save"]
}

# 写入文件 (dump)
# 使用 'w' 模式和 utf-8 编码
with open("config.json", "w", encoding="utf-8") as f:
    json.dump(config, f, indent=4, ensure_ascii=False)
print("配置文件 config.json 已保存。")

# 从文件读取 (load)
with open("config.json", "r", encoding="utf-8") as f:
    loaded_config = json.load(f)
print("\n从文件中加载的配置:")
print(loaded_config)
print(f"主题: {loaded_config['theme']}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 2. pickle 模块:Python 专用序列化协议

pickle 是 Python 特有的序列化模块。它使用二进制协议,几乎可以序列化任何 Python 对象,包括自定义类的实例、函数,甚至复杂的递归数据结构。

特点:

  • 功能强大: 支持几乎所有 Python 数据类型。
  • Python 专用: 序列化后的数据通常不能被其他语言理解。
  • 不保证向后兼容: 不同 Python 版本的 pickle 协议可能不兼容。
  • 安全风险: pickle 在反序列化时可以执行任意代码,因此绝对不要反序列化来自不可信或未经验证来源的数据!

# 2.1 序列化与反序列化

与 json 模块类似,pickle 也提供 dumps/loads 和 dump/load 四个核心函数。

import pickle
import datetime

class User:
    def __init__(self, name, last_login):
        self.name = name
        self.last_login = last_login
    
    def greet(self):
        print(f"你好, {self.name}! 你上次登录是在 {self.last_login}.")

# 创建一个复杂的对象,包含自定义类实例和 datetime 对象
user_data = {
    'user_obj': User("Alice", datetime.datetime.now()),
    'session_id': 12345,
    'permissions': {'read', 'write'} # set 类型,json 不支持
}

# 序列化为字节串 (bytes)
pickled_data = pickle.dumps(user_data)
print("--- Pickled 数据 (字节串) ---")
print(pickled_data)
print(f"\n类型: {type(pickled_data)}")

# 反序列化回 Python 对象
unpickled_data = pickle.loads(pickled_data)
print("\n--- 反序列化后的数据 ---")
print(unpickled_data)

# 反序列化后,对象的方法也可以正常调用
restored_user = unpickled_data['user_obj']
restored_user.greet()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 2.2 直接与文件交互

使用 pickle.dump() 和 pickle.load() 进行文件操作时,必须以二进制模式 ('wb' 或 'rb') 打开文件。

# 将对象保存到文件
with open("user_data.pkl", "wb") as f: # 'wb' -> write binary
    pickle.dump(user_data, f)
print("\n用户数据已保存到 user_data.pkl。")

# 从文件加载对象
with open("user_data.pkl", "rb") as f: # 'rb' -> read binary
    loaded_data_from_file = pickle.load(f)

print("\n从 pkl 文件加载的数据:")
loaded_data_from_file['user_obj'].greet()
1
2
3
4
5
6
7
8
9
10
11

# 3. json vs pickle 对比总结

特性 json pickle
数据格式 文本格式,人类可读 二进制格式,通常不可读
通用性 非常高,跨语言、跨平台的标准 仅限 Python,不同 Python 版本间可能不兼容
支持类型 基本数据类型 (dict, list, str, int, bool, None) 几乎所有 Python 对象 (包括自定义类、函数等)
性能 通常比 pickle 慢,但生成的文本更小 通常比 json 快,但生成的二进制文件可能更大
安全性 安全,只解析数据,不执行代码 极不安全,反序列化时可能执行任意代码,切勿用于不可信数据

如何选择?

  • 当你需要与 Web API、JavaScript前端 或 其他语言的程序 交互时,永远选择 json。
  • 当你需要持久化复杂的 Python 对象(如机器学习模型、游戏状态等),并且数据只在 Python 环境内部使用时,可以使用 pickle。但一定要确保数据的来源是完全可信的。
  • 对于通用的应用程序配置,优先选择 json 或其他人类可读的格式(如 YAML、TOML),因为它们更易于手动检查和修改。
编辑此页 (opens new window)
上次更新: 2025/07/25, 08:02:48
pip 包管理工具
requests 库 - HTTP for Humans

← pip 包管理工具 requests 库 - HTTP for Humans→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式