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

相关推荐
明月看潮生19 分钟前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
南宫理的日知录30 分钟前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
Mephisto.java34 分钟前
【大数据学习 | kafka高级部分】kafka的kraft集群
大数据·sql·oracle·kafka·json·hbase
Mephisto.java36 分钟前
【大数据学习 | kafka高级部分】kafka的文件存储原理
大数据·sql·oracle·kafka·json
coberup39 分钟前
django Forbidden (403)错误解决方法
python·django·403错误
逊嘘1 小时前
【Java语言】抽象类与接口
java·开发语言·jvm
Half-up1 小时前
C语言心型代码解析
c语言·开发语言
龙哥说跨境1 小时前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫
Source.Liu1 小时前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng1 小时前
【Rust中的迭代器】
开发语言·后端·rust