Python Pickle 与 JSON 序列化详解:存储、反序列化与对比

Python Pickle 与 JSON 序列化详解:存储、反序列化与对比

文章目录

  • [Python Pickle 与 JSON 序列化详解:存储、反序列化与对比](#Python Pickle 与 JSON 序列化详解:存储、反序列化与对比)
      • [一 功能总览](#一 功能总览)
      • [二 Pickle](#二 Pickle)
      • [三 Json](#三 Json)
        • [1 应用](#1 应用)
        • [2 序列化](#2 序列化)
        • [3 反序列化](#3 反序列化)
        • [4 不能序列化 class 类](#4 不能序列化 class 类)
      • [四 Pickle 和 Json 对比](#四 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 数据

python 复制代码
		# import pickle	
		data = {"filename": "f1.txt", "create_time": "today", "size": 111}
		print(pickle.dumps(data))
2 序列化

将数据转换成文件储存

python 复制代码
    # 用 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 类

python 复制代码
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 文件中 反序列化回来

python 复制代码
    # 打包类,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)不能被序列化的系统资源对象

注:依赖外部系统状态的对象不能被序列化,比如 打开文件,网络连接,线程,进程,栈帧等等。

python 复制代码
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

python 复制代码
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"])

示例

python 复制代码
 # 硬要用依赖外部系统状态的对象去 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 应用
python 复制代码
# Json
# import json
data = {"filename": "f1.txt", "create_time": "today", "size": 111}
j = json.dumps(data)
print(j)
print(type(j))
2 序列化

Json 储存数据

python 复制代码
# 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 反序列化
python 复制代码
print("用 json 加载了读:")
with open("data.json", "r") as f:
    new_data = json.load(f)
print("字典读取:", new_data["filename"])
4 不能序列化 class 类
python 复制代码
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 可以跨多语言读写
处理时间 长(需编码数据) 短(不需编码)
安全性 不安全(除非你信任数据源) 相对安全

五 完整代码示例

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 中运行,运行结果如下。

nginx 复制代码
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

六 源码地址

代码地址:

国内看 Giteepickle 和 json序列化.py

国外看 GitHubpickle 和 json序列化.py

引用 莫烦 Python

相关推荐
luoluoal1 分钟前
java项目之企业级工位管理系统源码(springboot)
java·开发语言·spring boot
ch_s_t3 分钟前
新峰商城之购物车(一)
java·开发语言
yukai080087 分钟前
Python 全栈系列271 微服务踩坑记
python·微服务·php
亚林瓜子24 分钟前
Jackson注解屏蔽某些字段读取权限
spring·json·jackson
学步_技术27 分钟前
Python编码系列—Python工厂方法模式:构建灵活对象的秘诀
开发语言·python·工厂方法模式
秋秋秋叶39 分钟前
Python学习——【2.3】for循环
python·学习
Deryck_德瑞克1 小时前
Java集合笔记
java·开发语言·笔记
MengYiKeNan1 小时前
C++二分函数lower_bound和upper_bound的用法
开发语言·c++·算法
会发paper的学渣1 小时前
python 单例模式实现
开发语言·python·单例模式
学步_技术1 小时前
Python编码系列—Python桥接模式:连接抽象与实现的桥梁
开发语言·python·桥接模式