Python Pickle 与 JSON 序列化详解:存储、反序列化与对比
文章目录
- Python Pickle 与 JSON 序列化详解:存储、反序列化与对比
 - 一 功能总览
 - 二 Pickle
 - 1 应用
 - 2 序列化
 - 3 反序列化
 - 4 系统资源对象
 - 1)不能被序列化的系统资源对象
 - 2)强行序列化系统资源对象
 
- 三 Json
 - 1 应用
 - 2 序列化
 - 3 反序列化
 - 4 不能序列化 class 类
 
- 四 Pickle 和 Json 对比
 - 五 完整代码示例
 - 六 源码地址
 
在 Python 中,序列化是保存数据和对象的重要方式,其中 Pickle 和 JSON 是常用的两种序列化方法。本文详细介绍了如何使用 Pickle 和 JSON 进行数据和类的序列化与反序列化操作。通过 Pickle,能够将 Python 对象保存为二进制文件,而 JSON 更适用于跨语言的数据交换。文章包含了 Pickle 的序列化、反序列化,以及如何处理系统资源对象。还涵盖了 JSON 的基本操作及其与 Pickle 的对比,帮助开发者根据不同场景选择合适的序列化方式。
一 功能总览
| Pickle | Json | 
|---|---|
| pickle.dumps() | json.dumps() | 
| pickle.dump() | json.dump() | 
| pickle.load() | json.load() | 
二 Pickle
1 应用
使用 pickle 去 dumps 数据
		# import pickle	
		data = {"filename": "f1.txt", "create_time": "today", "size": 111}
		print(pickle.dumps(data))
 
2 序列化
将数据转换成文件储存
    # 用 pickle.dump() 将字典直接转换成一个文件。
    data = {"filename": "f1.txt", "create_time": "today", "size": 111}
    with open("data.pkl", "wb") as f:
        pickle.dump(data, f)
    print(os.listdir())
    with open("data.pkl", "rb") as f:
        data = pickle.load(f)
    print(data)
 
3 反序列化
pickle 可以将 类打包成文件,然后 unpickle 还原回来,File 类
class File:
    def __init__(self, name, create_time, size):
        self.name = name
        self.create_time = create_time
        self.size = size
    def change_name(self, new_name):
        self.name = new_name
 
从 data.pkl 文件中 反序列化回来
    # 打包类,File类
    data = File("f2.txt", "now", 222)
    # 存
    with open("data.pkl", "wb") as f:
        pickle.dump(data, f)
    # 读
    with open("data.pkl", "rb") as f:
        read_data = pickle.load(f)
    print(read_data.name)
    print(read_data.size)
 
4 系统资源对象
1)不能被序列化的系统资源对象
注:依赖外部系统状态的对象不能被序列化,比如 打开文件,网络连接,线程,进程,栈帧等等。
class File02:
    def __init__(self, name, create_time, size):
        self.name = name
        self.create_time = create_time
        self.size = size
        # 打开文件
        self.file = open(name, "w")
    # 依赖外部系统状态的对象不能被序列化,比如 打开的文件,网络连接,线程,进程,栈帧等等。
    # data = File02("f3.txt", "now", 222)
    # pickle 存,会报错
    # TypeError: cannot pickle '_io.TextIOWrapper' object
    # with open("data.pkl", "wb") as f:
    #     pickle.dump(data, f)
 
2)强行序列化系统资源对象
硬要用依赖外部系统状态的对象去 pickle 保存,可以规避一下,看 类 File03
class File03:
    def __init__(self, name, create_time, size):
        self.name = name
        self.create_time = create_time
        self.size = size
        self.file = open(name, "w")
    def __getstate__(self):
        # pickle 出去需要且能被 pickle 的信息
        pickled = {"name": self.name, "create_time": self.create_time, "size": self.size}
        return pickled
    def __setstate__(self, pickled_dict):
        # unpickle 加载回来,重组 class
        self.__init__(
            pickled_dict["name"], pickled_dict["create_time"], pickled_dict["size"])
 
示例
 # 硬要用依赖外部系统状态的对象去 pickle 保存,可以规避一下
    # pickle.dump() 会调用 __getstate__() 获取序列化的对象。 __setstate__() 在反序列化时被调用。
    data = File03("f3.txt", "now", 222)
    # 存
    with open("data.pkl", "wb") as f:
        pickle.dump(data, f)
    # 读
    with open("data.pkl", "rb") as f:
        read_data = pickle.load(f)
    print(read_data.name)
    print(read_data.size)
    print()
 
三 Json
1 应用
# Json
# import json
data = {"filename": "f1.txt", "create_time": "today", "size": 111}
j = json.dumps(data)
print(j)
print(type(j))
 
2 序列化
Json 储存数据
# Json 储存数据
data = {"filename": "f1.txt", "create_time": "today", "size": 111}
with open("data.json", "w") as f:
    json.dump(data, f)
print("直接当纯文本读:")
with open("data.json", "r") as f:
    print(f.read())
 
3 反序列化
print("用 json 加载了读:")
with open("data.json", "r") as f:
    new_data = json.load(f)
print("字典读取:", new_data["filename"])
 
4 不能序列化 class 类
class File04:
    def __init__(self, name, create_time, size):
        self.name = name
        self.create_time = create_time
        self.size = size
    def change_name(self, new_name):
        self.name = new_name
#  json 不能序列化保存 class
# TypeError: Object of type File is not JSON serializable
data = File04("f4.txt", "now", 222)
# 存,会报错
# with open("data.json", "w") as f:
#     json.dump(data, f)
 
四 Pickle 和 Json 对比
| 对比 | Pickle | Json | 
|---|---|---|
| 存储格式 | Python 特定的 Bytes 格式 | 通用 JSON text 格式,可用于常用的网络通讯中 | 
| 数据种类 | 类,功能,字典,列表,元组等 | 基本和 Pickle 一样,但不能存类,功能 | 
| 保存后可读性 | 不能直接阅读 | 能直接阅读 | 
| 跨语言性 | 只能用在 Python | 可以跨多语言读写 | 
| 处理时间 | 长(需编码数据) | 短(不需编码) | 
| 安全性 | 不安全(除非你信任数据源) | 相对安全 | 
五 完整代码示例
# This is a sample Python script.
# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
import pickle
import os
import json
class File04:
    def __init__(self, name, create_time, size):
        self.name = name
        self.create_time = create_time
        self.size = size
    def change_name(self, new_name):
        self.name = new_name
class File03:
    def __init__(self, name, create_time, size):
        self.name = name
        self.create_time = create_time
        self.size = size
        self.file = open(name, "w")
    def __getstate__(self):
        # pickle 出去需要且能被 pickle 的信息
        pickled = {"name": self.name, "create_time": self.create_time, "size": self.size}
        return pickled
    def __setstate__(self, pickled_dict):
        # unpickle 加载回来,重组 class
        self.__init__(
            pickled_dict["name"], pickled_dict["create_time"], pickled_dict["size"])
class File02:
    def __init__(self, name, create_time, size):
        self.name = name
        self.create_time = create_time
        self.size = size
        self.file = open(name, "w")
class File:
    def __init__(self, name, create_time, size):
        self.name = name
        self.create_time = create_time
        self.size = size
    def change_name(self, new_name):
        self.name = new_name
def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press ⌘F8 to toggle the breakpoint.
    # 主要涉及到的功能
    # Pickle
    # pickle.dumps()
    # pickle.dump()
    # pickle.load()
    # Json
    # json.dumps()
    # json.dump()
    # json.load()
    data = {"filename": "f1.txt", "create_time": "today", "size": 111}
    print(pickle.dumps(data))
    # 用 pickle.dump() 将字典直接转换成一个文件。
    data = {"filename": "f1.txt", "create_time": "today", "size": 111}
    with open("data.pkl", "wb") as f:
        pickle.dump(data, f)
    print(os.listdir())
    with open("data.pkl", "rb") as f:
        data = pickle.load(f)
    print(data)
    # 打包类,File类
    data = File("f2.txt", "now", 222)
    # 存
    with open("data.pkl", "wb") as f:
        pickle.dump(data, f)
    # 读
    with open("data.pkl", "rb") as f:
        read_data = pickle.load(f)
    print(read_data.name)
    print(read_data.size)
    # 依赖外部系统状态的对象不能被序列化,比如 打开的文件,网络连接,线程,进程,栈帧等等。
    # data = File02("f3.txt", "now", 222)
    # pickle 存,会报错
    # TypeError: cannot pickle '_io.TextIOWrapper' object
    # with open("data.pkl", "wb") as f:
    #     pickle.dump(data, f)
    # 硬要用依赖外部系统状态的对象去 pickle 保存,可以规避一下
    # pickle.dump() 会调用 __getstate__() 获取序列化的对象。 __setstate__() 在反序列化时被调用。
    data = File03("f3.txt", "now", 222)
    # 存
    with open("data.pkl", "wb") as f:
        pickle.dump(data, f)
    # 读
    with open("data.pkl", "rb") as f:
        read_data = pickle.load(f)
    print(read_data.name)
    print(read_data.size)
    print()
    # Json
    data = {"filename": "f1.txt", "create_time": "today", "size": 111}
    j = json.dumps(data)
    print(j)
    print(type(j))
    print()
    # Json 储存数据
    data = {"filename": "f1.txt", "create_time": "today", "size": 111}
    with open("data.json", "w") as f:
        json.dump(data, f)
    print("直接当纯文本读:")
    with open("data.json", "r") as f:
        print(f.read())
    print("用 json 加载了读:")
    with open("data.json", "r") as f:
        new_data = json.load(f)
    print("字典读取:", new_data["filename"])
    print()
    #  json 不能序列化保存 class
    # TypeError: Object of type File is not JSON serializable
    data = File04("f4.txt", "now", 222)
    # 存,会报错
    # with open("data.json", "w") as f:
    #     json.dump(data, f)
    # Pickle 和 Json 的不同
    # 存储格式  Python 特定的 Bytes 格式   通用 JSON text 格式,可用于常用的网络通讯中
    # 数据种类  类,功能,字典,列表,元组等  基本和 Pickle 一样,但不能存类,功能
    # 保存后可读性  不能直接阅读  能直接阅读
    # 跨语言性  只能用在 Python  可以跨多语言读写
    # 处理时间  长(需编码数据)  短(不需编码)
    # 安全性  不安全(除非你信任数据源) 相对安全
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print_hi('pickle 和 json 序列化')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
 
复制粘贴并覆盖到你的 main.py 中运行,运行结果如下。
Hi, pickle 和 json 序列化
b'\x80\x04\x958\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x08filename\x94\x8c\x06f1.txt\x94\x8c\x0bcreate_time\x94\x8c\x05today\x94\x8c\x04size\x94Kou.'
['new_file4.txt', 'Function 函数.py', 'new_file5.txt', '如何控制异常 try-except.py', 'new_file.txt', 'me.py', 'new_file2.txt', '.DS_Store', 'new_file3.txt', 'f3.txt', 'Module 模块.py', 'chinese.txt', 'no_file.txt', 'module', 'user', '数据种类.py', '__pycache__', 'data.json', 'project', '正则表达式.py', 'file.py', '单元测试.py', 'pickle 和 json序列化.py', '变量与运算.py', 'data.pkl', '文件目录管理.py', '条件判断.py', 'Class 类.py', 'main.py', '读写文件.py', 'for 和 while 循环.py', '.idea']
{'filename': 'f1.txt', 'create_time': 'today', 'size': 111}
f2.txt
222
f3.txt
222
{"filename": "f1.txt", "create_time": "today", "size": 111}
<class 'str'>
直接当纯文本读:
{"filename": "f1.txt", "create_time": "today", "size": 111}
用 json 加载了读:
字典读取: f1.txt
 
六 源码地址
代码地址:
国内看 Gitee 之 pickle 和 json序列化.py
国外看 GitHub 之 pickle 和 json序列化.py
引用 莫烦 Python



















