[Python学习日记-50] Python 中的序列化模块 —— pickle 和 json

news2024/10/21 7:48:37

[Python学习日记-50] Python 中的序列化模块 —— pickle 和 json

简介

pickle 模块

json 模块

pickle VS json

简介

        什么叫序列化?

        序列化指的是将对象转换为可以在网络上传输或者存储到文件系统中的字节流的过程。序列化使得对象可以被保存、传输和恢复,而不损失其状态和属性。在序列化过程中,对象的属性和数据会被编码为二进制数据,以便能够在不同的环境中被解码和重建成原来的对象。常见的序列化格式有 JSON、XML 和二进制格式等。简单来说就是把内存里的数据类型转换成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受以字节(bytes)的形式进行存储或传输。

        有了序列化,那有没有反序列化呢?

        当然有了,反序列化是序列化的逆过程,指的是将序列化后的字节流重新转换为对象的过程。通过反序列化,可以将保存在文件系统或者网络中的对象数据重新还原为内存中的对象,使其恢复原有的状态和属性。反序列化过程将二进制数据解码并重新构建为原始对象,并将其存储在内存中,以便程序可以直接使用这些对象。反序列化是序列化的重要补充,它使得可以在不同的环境或者平台之间传递对象数据,并在接收方重新构建对象。简单来说就是把存储在硬盘当中的字节或者是网络传输过来的字节转换为相应的数据类型,使其能在对应的程序中使用传输过来的数据。

        其实这个过程非常像科幻电影里面的光速移动,先把人编码为光信号,然后传输到目的地,最后在目的地接收该光信号,然后通过光信号中的信息,把人还原回来。

        有的小伙伴还是不明白,为什么要这么大费周章的进行序列化呢?我们举个例子,例如你在打《使命召唤》,在这个过程中打累了,想要停下来关掉游戏2天再玩,在2天之后游戏又从你上次停止的地方继续运行,那你上次游戏的进度肯定保存在硬盘上了,不然你电脑一断电内存里的数据肯定就没了,它是以何种形式来存储的呢?而且游戏过程中产生的很多临时数据都是不规律的,可能在你关掉游戏时正好有10个列表,3个嵌套字典的数据集合在内存里,而这些都需要存下来,那该怎么存呢?把列表变成文件里的多行多列形式?但是嵌套字典根本没法以该形式进行储存啊。所以,若是有种办法可以直接把内存数据存到硬盘上,下次程序再启动,再从硬盘上读回来,还是原来的格式的话,那是极好的。而这个需求恰恰就是序列化模块的功能了,在 Python 中有两个序列化模块:pickle(用于 Python 特有的类型和 Python 的数据类型间进行转换)和 json(用于字符串和 Python 数据类型间进行转换),下面我们分别来看看他们的用法。

pickle 模块

        pickle 模块提供了四个功能:dumps、dump、loads、load

一、序列化

  • dumps:生成序列化的字符串在内存当中,代码如下
import pickle

d = {
    "name":"jove",
    "role":"police",
    "blood":76,
    "weapon":"M4A1"
}

alive_players = ["jove","kerry","lucy"]

d_dump = pickle.dumps(d)    # 序列化
print(d_dump)

代码输出如下:

  • dump:生成序列化的字符串并写入文件,代码如下
import pickle

d = {
    "name":"jove",
    "role":"police",
    "blood":76,
    "weapon":"M4A1"
}

alive_players = ["jove","kerry","lucy"]

f = open('game.pkl','wb')    # pickle 序列化后是字节,所以需要用 wb,读需要用 rb
pickle.dump(d,f) # 序列化存入文件
pickle.dump(alive_players,f)

代码效果如下:

        之所以是乱码,是因为 PyCharm 想要以 UTF-8 强行解码导致的。  

二、反序列化

  • loads:把内存当中的序列化字符串进行反向解析,代码如下
import pickle

d = {
    "name":"jove",
    "role":"police",
    "blood":76,
    "weapon":"M4A1"
}

alive_players = ["jove","kerry","lucy"]

d_dump = pickle.dumps(d)    # 序列化
print(d_dump)
print(pickle.loads(d_dump))    # 反序列化

代码输出如下:

  • load:从文件加载序列化的字符串反向解析到内存当中,代码如下
'''
game.pkl 内容:
\x80\x04\x95=\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x04jove\x94\x8c\x04role\x94\x8c\x06police\x94\x8c\x05blood\x94KL\x8c\x06weapon\x94\x8c\x04M4A1\x94u.
'''

import pickle


f = open('game.pkl','rb')
# First in first out --> FIFO 先入先出
# First in last out --> FILO 先入后出
d = pickle.load(f)    # 反序列化,从文件取出来
print(d)
alive_plays = pickle.load(f)
print(alive_plays)

代码输出如下: 

        结合上面序列化存入文件时的代码输出,我们知道 pickle 模块在多个数据类型进行序列化的时候,是 First in first out(FIFO)类型的,即先先入先出。

json 模块

        json 模块也提供了四个功能:dumps、dump、loads、load,用法跟 pickle 一致

一、序列化

  • dumps:生成序列化的字符串在内存当中,代码如下
import json

d = {
    "name":"jove",
    "role":"police",
    "blood":76,
    "weapon":"M4A1"
}

alive_players = ["jove","kerry","lucy"]

d_dump = json.dumps(d)

print(d_dump)
print(type(d_dump))    # pickle是bytes,但json是str

代码输出如下:

  • dump:生成序列化的字符串并写入文件,代码如下
import json

d = {
    "name":"jove",
    "role":"police",
    "blood":76,
    "weapon":"M4A1"
}

alive_players = ["jove","kerry","lucy"]

f = open('game.json','w')    # json.dumps(d)转换为的是str,所以只需要'w'就可以了

json.dump(d,f)

代码效果如下:

二、反序列化

  •  loads:把内存当中的序列化字符串进行反向解析,代码如下
import json

d = {
    "name":"jove",
    "role":"police",
    "blood":76,
    "weapon":"M4A1"
}

alive_players = ["jove","kerry","lucy"]

d_dump = json.dumps(d)
print(type(d_dump))
d_load = json.loads(d_dump)
print(d_load["weapon"])

代码输出如下:

  •  load:从文件加载序列化的字符串反向解析到内存当中,代码如下
'''
game.json 内容:
{"name": "jove", "role": "police", "blood": 76, "weapon": "M4A1"}
'''

import json

f = open('game.json','r')

d = json.load(f)
print(d,type(d))
print(d["weapon"])

代码输出如下:

pickle VS json

Pickle:

优点:专为 Python 设计,支持 Python 所有的数据类型,例如class->object、function、datetime等
缺点:只能在 Python 中使用,而且存储数据占空间大

JSON:

优点:跨语言(不同编程语言之间的数据传递可用 json 交接)、存储数据占空间小
缺点:只能支持 int、str、list、tuple、dict 这类比较常规的数据类型

一、dump 次数

        pickle 可以 dump 多次,json 只能 dump 一次,主要问题是出现在读取的时候,分别使用 pickle 和 json 进行多次 dump,game.pkl 和 game.json,代码如下

import pickle
import json

d = {
    "name":"jove",
    "role":"police",
    "blood":76,
    "weapon":"M4A1"
}

alive_players = ["jove","kerry","lucy"]

f_p = open('game.pkl','wb')
pickle.dump(d,f_p)
pickle.dump(alive_players,f_p)

f_j = open('game.json','w')
json.dump(d,f_j)
json.dump(alive_players,f_j)

代码效果如下:

        可以看到,数据已经成功序列化后写入到硬盘当中了,这时候我们来把数据 load 出来看看问题到底是什么,代码如下

import pickle
import json

f_p = open("game.pkl","rb")
print("pickle1:",pickle.load(f_p))
print("pickle2:",pickle.load(f_p))

f_j = open("game.json","r")
print("json1:",json.load(f_j))
print("json2:",json.load(f_j))

代码输出如下:

        从输出结果来看,很明显 json 不能像 pickle 一样进行多次 dump,这是与 json 的文件写入有关,我们在仔细看看 json 进行多次 dump 之后写入的到底是什么,看下图

        多次 dump 的写入内容都是拼在一起的,并没有什么特殊字符用作分割,所以 json.load 尝试反向解析的时候就会把全部 game.json 里面的内容都读出来,但是它发现这个并不认识,所以最终就会抛出 json.decoder.JSONDecodeError 的错误,即 json 解码失败。

二、pickle 序列化非常规数据类型

        我们以 datetime 对象为例,分别使用 pickle 和 json 进行 dump 操作,代码如下

import pickle
import json
import datetime

t = datetime.datetime.now()
print(t,type(t))
tp_dump = pickle.dumps(t)
print(tp_dump)
tj_dump = json.dumps(t)

代码输出如下:

        从输出结果来看,很明显 json 不能像 pickle 一样序列化 datetime 对象,而是直接抛出 TypeError 报错,这是因为 json 的其中一个特性就是跨语言,而不同语言之间的语法定义都是不一样的,如果需要把所有语言的语法定义都进行识别然后转换,那这个工作将会无比复杂,所以 json 就干脆只支持一些常规的数据类型,因为这些数据类型几乎在所有语言当中都有。

        再举个实际场景,例如我要开发一个网站,而网站是分前后端的,前端我们使用的语言是 html、js、css,而后端我们使用的是 Python 那如果我们要进行对接那应该怎么做呢?能把整个 function 序列化到前端语言中运行吗?这显然是不行的,我们以 js 和 Python 为例来对比一下

js 中定义的 function:

fName (x,x,x){
        xxxx
}

 

Python 中定义的 function:

def fname():

        xxxxx

        可以很明显的看出,两种语法完全不同,而 json 是需要先把数据类型转换为字符串,然后在进行传输或储存的,最后原封不动的传到取其他语言当中。而当其他语言拿到了传过来的 json 文件时惊呆了,这个 function 的语法居然是它不认识的,那它只能无奈的报错了。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2219898.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3D Slicer 教程二 ---- 数据集

上一章下载3d slicer的软件,这章从加载数据集来弄清楚3dslicer怎么使用. 一. 加载数据集 如果没有数据集,也可用用样本数据. (1) "File" --> "add Data" 可以添加图片文件夹,(试了MP4不行,内镜的视频估计不支持),添加单个图片的话,会出现一些选项, …

C++贪心

前言 C算法与数据结构 打开打包代码的方法兼述单元测试 简介 贪心算法(Greedy Algorithm)是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法策略。贪心算…

【设计模式系列】抽象工厂模式

一、什么是抽象工厂模式 抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。这种模式允许客户端使用抽象的接口来创建一组…

AUTOSAR_EXP_ARAComAPI的5章笔记(17)

☞返回总目录 相关总结:AutoSar AP CM通信组总结 5.7 通信组 5.7.1 目标 通信组(Communication Group,CG)是由 AUTOSAR 定义的复合服务模板。它提供了一个通信框架,允许在 AUTOSAR 应用程序之间以对等方式和广播模…

第6章 元素应用CSS作业

1.使用CSS对页面网页元素加以修饰&#xff0c;制作“旅游攻略”网站。 浏览效果如下&#xff1a; HTML代码如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>旅游攻略</title><link type"t…

[JAVAEE] 线程安全问题

目录 一. 什么是线程安全 二. 线程安全问题产生的原因 三. 线程安全问题的解决 3.1 解决修改操作不是原子性的问题 > 加锁 a. 什么是锁 b. 没有加锁时 c. 加锁时 d. 死锁 e. 避免死锁 3.2 解决内存可见性的问题 > volatile关键字 (易变的, 善变的) a. 不加…

【Linux】多线程安全之道:互斥、加锁技术与底层原理

目录 1.线程的互斥 1.1.进程线程间的互斥相关背景概念 1.2.互斥量mutex的基本概念 所以多线程之间为什么要有互斥&#xff1f; 为什么抢票会抢到负数&#xff0c;无法获得正确结果&#xff1f; 为什么--操作不是原子性的呢&#xff1f; 解决方式&#xff1a; 2.三种加锁…

git add操作,文件数量太多卡咋办呢,

git add介绍 Git的add命令是用于将文件或目录添加到暂存区&#xff08;也就是索引库&#xff09;&#xff0c;以便在后续的提交&#xff08;commit&#xff09;操作中一并上传到版本库的。具体来说&#xff0c;git add命令有以下几种常见用法&#xff1a; 添加单个文件&#…

4、.Net 快速开发框架:DncZeus - 开源项目研究文章

DncZeus 是一个基于 ASP.NET Core 和 Vue.js 的前后端分离的通用后台管理系统框架&#xff0c;其愿景是成为一个易于使用且功能丰富的 .NET Core 通用后台权限管理模板系统基础框架。项目名称 "DncZeus" 由 "Dnc"(.NET Core 的缩写)和 "Zeus"(古…

CLion和Qt 联合开发环境配置教程(Windows和Linux版)

需要安装的工具CLion 和Qt CLion下载链接 :https://www.jetbrains.com.cn/clion/ 这个软件属于直接默认安装就行&#xff0c;很简单&#xff0c;不多做介绍了 Qt:https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/online_installers/ window 直接点exe Linux 先c…

el-table动态新增/删除表单行及校验规则

方式一&#xff1a; <template><el-form ref"ruleFormRef" :model"ruleForm" :rules"rules" label-width"120px" class"model-ruleForm":size"formSize" status-icon label-position"top">…

堆的使用实例

小伙伴们大家好&#xff0c;今天为大家带来一道算法题&#xff1a; 分析题意我们可知&#xff1a;数组最小元素一定位于0~k位置&#xff0c;如果我们首先将0~k位置构成最小堆&#xff0c;那么堆顶一定就是数组最小值。将堆顶拿出&#xff0c;将数组k1位置放入&#xff0c;那么数…

无人机+视频推流直播EasyCVR视频汇聚/EasyDSS平台在森林防护巡检中的解决方案

随着科技的飞速发展&#xff0c;无人机技术在各个领域的应用日益广泛&#xff0c;特别是在森林防护与巡检方面&#xff0c;无人机以其独特的优势&#xff0c;为传统林业管理带来了革命性的变化。本文将探讨无人机在森林防护巡检中的解决方案&#xff0c;分析其工作原理、优势及…

MYSQL 拼接函数

目录 1、CONCAT 2、CONCAT_WS 1、CONCAT 解释&#xff1a;用于拼接两个或多个字符串成一个字符串。如果任何一个参数为 NULL&#xff0c;则 CONCAT 函数的结果也会是 NULL。 语法格式&#xff1a;SELECT concat(column_name1,column_name2,...) FROM table_name 中文注释&…

【verilog刷题】时钟切换电路

时钟切换电路 1.基本概念-相关时钟源和无关时钟源2.基本的时钟切换电路&#xff08;组合逻辑&#xff09;2.相关时钟源无毛刺时钟切换电路3.非相关时钟源无毛刺时钟切换电路 1.基本概念-相关时钟源和无关时钟源 相关时钟源&#xff1a;时钟信号源之间存在某种同步或关联的关系…

[含文档+PPT+源码等]精品基于Nodejs实现的医院问诊系统的设计与实现

基于Node.js实现的医院问诊系统的设计与实现背景主要源于以下几个方面&#xff1a; 一、医疗行业变革的需求 随着互联网的飞速发展&#xff0c;特别是移动互联网技术的广泛应用&#xff0c;传统医疗行业正经历着前所未有的变革。医疗资源分布不均、患者就医难等问题日益凸显&…

数据结构单向链表的插入和删除(一)

链表 一、链表结构&#xff1a; &#xff08;物理存储结构上不连续&#xff0c;逻辑上连续&#xff1b;大小不固定&#xff09;二、单链表&#xff1a;三、单项链表的代码实现&#xff1a;四、开发可用的链表&#xff1a;四、单链表的效率分析&#xff1a; 一、链表结构&#x…

爬虫结合项目实战

由于本人是大数据专业&#xff0c;所以准备的是使用pycharm工具进行爬虫爬取数据&#xff0c;然后实现一个可视化大屏 参考项目&#xff1a; 1.医院大数据可视化最后展示 2. 大数据分析可视化系统展示 代码包&#xff1a;

如何防止SpringBoot中的jar反编译?解决相关报错及踩到的坑

目录 1. 面对的场景 2. 方案 2.1 使用代码混淆 2.2 JAR包加密 3. 项目操作 4. 启动方式 5. 踩到的各种坑 5.1 java -jar xxx-0.0.1-SNAPSHOT.jar 没有主清单属性 5.2 Caused by: java.lang.IllegalArgumentException: Unrecognized option: -pwdfxw-jar 1. 面对的场景…

sql-labs靶场第十七关测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、寻找注入点 2、注入数据库 ①寻找注入方法 ②爆库&#xff0c;查看数据库名称 ③爆表&#xff0c;查看security库的所有表 ④爆列&#xff0c;查看users表的所有列 ⑤成功获取用户名…