添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Python3教程014:Python3中4个用于序列化与反序列化对象的模块

Python3教程014:Python3中4个用于序列化与反序列化对象的模块

文章是 安泽频道 原创且经过实际操作验证,大家可以放心引用。

在Python3编程中,我们经常需要将一些内存中的对象保存到文件或者发布到网络,此时我们就需要将内存中的对象序列化,只有序列化之后才能存储或者传输。 所谓的序列化 就是将内存对象转换为二进制串 。Python3中与序列化相关的模块有4个,分别为json、pickle、shelve、struct,本文将会分享它们的作用及使用方法。

一.json模块的作用及使用方法

我们平常所说的json是一种保存数据的格式,但今天本文中所讲的json是一个用于对json格式的数据进行序列化与反序列化的Python3模块。

1.json数据的具体格式

  • 数据通过键值对配对。
  • 键名用双引号包裹,后面是“:”,然后是键值。
  • 键值可为字符串、数字、列表、对象等数据类型。
  • 各个键值对之间用逗号隔开。

一个典型的json格式数据如下代码所示。

# 在json格式的数据中注意区别{}与[]中包含的数据的格式
# {}中包含的是一个字典对象,[]中包含的是一个列表对象
dict_anze = {
    "注意": "json格式的数据中尽量使用双引号,不要使用单引号",
    "name": "安泽频道",
    "contact": [
            "email": "348834851@qq.com",
            "multimedia": {
                "douyin": ["抖音号", "anzechannel"], "kuaishou":["快手号", "anzechannel"]
            "email": "anzechannel@qq.com",
            "multimedia": {
                "github": ["github号", "anzechannel"], "pypi":["pypi号", "anzechannel"]
}

2.json模块中的dumps函数

dumps函数可以将dict对象编码为一个json格式的字符串类型数据,具体代码如下所示。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# 模块说明板块
# =============================================================================
本文作者:安泽频道
抖音号码:anzechannel
快手号吗:anzechannel
联系邮箱:348834851@qq.com
创建日期:2021-11-23 21:52:36
编程软件:Win10专业版操作系统中Anaconda3虚拟的Python3.8环境中的spyder5.1.5
模块功能:Python3的json模块中dumps函数使用方法
import json
# 在json格式的数据中注意区别{}与[]中包含的数据的格式
# {}中包含的是一个字典对象,[]中包含的是一个列表对象
dict_anze = {
    "注意": "json格式的数据中尽量使用双引号,不要使用单引号",
    "name": "安泽频道",
    "contact": [
            "email": "348834851@qq.com",
            "multimedia": {
                "douyin": ["抖音号", "anzechannel"], "kuaishou":["快手号", "anzechannel"]
            "email": "anzechannel@qq.com",
            "multimedia": {
                "github": ["github号", "anzechannel" ], "pypi":["pypi号", "anzechannel" ]
# =============================================================================
# json.dumps函数将字典对象序列化为字符串对象,参数如下
# 1.skipkey,默认为False,当dict对象里的数据不是Python的基本数据类型(str, unicode, int, long, float, bool, None时,
# 若skipkey为False,报错,若skipkey为True,跳过该key。
# 2.indent,正整数类型,如果不填,则打印为一行,否则在前面层级显示indent数量的空格,
# 是一个美化打印效果的参数。
# 3.separators,分隔符,默认为“(',', ':')”,表示key之间用“,”隔开,key和value之间用“:”隔开。
# 4.encoding,编码格式,默认UTF-8。
# 5.sort_keys,对key、value进行排序,默认值是False,即不排序。
# 6.ensure_ascii,默认True,如果dict对象里含有none-ascii字符,则显示为\uxx格式,如果为False,则正常显示。
# =============================================================================
json_anze = json.dumps(dict_anze, sort_keys=True, indent=4, ensure_ascii=False)
print(json_anze)
# 查看json.dumps函数返回值的类型
print('json_anze的数据类型是:', type(json_anze))

上述代码执行后的结果如下图所示。

json.dumps函数将一个字典对象转换为字符串对象

3.json模块中的loads函数

loads函数可以将一个json格式的字符串类型数据解码为dict对象,具体代码如下所示。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# 模块说明板块
# =============================================================================
本文作者:安泽频道
抖音号码:anzechannel
快手号吗:anzechannel
联系邮箱:348834851@qq.com
创建日期:2021-11-23 21:52:36
编程软件:Win10专业版操作系统中Anaconda3虚拟的Python3.8环境中的spyder5.1.5
模块功能:Python3的json模块中loads函数使用方法
import json
# 一个字符串变量
str_anze = '{"姓名": "安泽频道","QQ": "348834851"}'
# json.loads函数将json格式的字符串变量反序列化为字典对象
dict_anze = json.loads(str_anze)
# 字典中通过键名获取键值
print(dict_anze['姓名'])
# 查看json.loads函数返回值的类型
print('dict_anze的数据类型是:', type(dict_anze))

上述代码执行后的结果如下图所示。

json.loads函数将一个字符串对象转换为字典对象

4.json模块中的dump和load函数

dump函数将字典对象序列化为文件中的字符串,load函数将文件中的字符串反序列化为字典对象。dumps和loads函数处理程序中的字符串,而dump和load函数处理程序外的文本文件。dump和load函数主要用于读写配置文件,与configparser模块的功能有些相似,具体代码如下。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# 模块说明板块
# =============================================================================
本文作者:安泽频道
抖音号码:anzechannel
快手号吗:anzechannel
联系邮箱:348834851@qq.com
创建日期:2021-11-23 21:52:36
编程软件:Win10专业版操作系统中Anaconda3虚拟的Python3.8环境中的spyder5.1.5
模块功能:Python3的json模块中dump函数和load函数使用方法
import json
dict_anze = {"姓名": "安泽频道", "QQ": "348834851"}
# 打开dump_anze文件并将序列化后的字典写入文本文件
with open('dump_anze', 'w', encoding='utf-8') as dump_file:
    # 等价于dump_file.write(json.dumps(dict_anze, indent=4))
    json.dump(dict_anze, dump_file, sort_keys=True,
              indent=4, ensure_ascii=False)
print('dump函数生成了文本文件dump_anze')
# 打开load_anze文件并将文本文件反序列化为字典
# 需要注意的是load_anze文件中不能有空格换行等特殊符号,必须严格满足json数据格式要求
# 否则文件读取失败,会报JSONDecodeError: Expecting value
with open('load_anze', encoding='utf-8') as load_file:
    # 等价于dict_data = json.loads(load_file.read())
    dict_data = json.load(load_file)
# 打印从文件中读取出来的'注意'键的键值
print('load函数从load_anze文本文件中读取的"注意"键的键值是:', dict_data["注意"])

load_anze文本文件中的内如及其格式如下,需要注意的是load函数读取的文本文件的格式必须严格满足json数据格式要求, 文件中不能有空格换行等特殊符号 ,否则会报raise JSONDecodeError("Expecting value", s, err.value) from None、JSONDecodeError: Expecting value错误。

{"注意":"json格式的数据中尽量使用双引号,不要使用单引号","name":"安泽频道","contact":[{"email":"348834851@qq.com","multimedia":{"douyin":["抖音号","anzechannel"],"kuaishou":["快手号","anzechannel"]},"email":"anzechannel@qq.com","multimedia":{"github":["github号","anzechannel"],"pypi":["pypi号","anzechannel"]}}]}

程序执行结果如下图所示,dump函数生成了一个文本文件dump_anze。

dump函数生成文本文件,load函数读取文本文件

dump函数生成的文本文件dump_anze的内容如下图所示。

dump函数生成的文本文件dump_anze的内容

Python3中json模块的相关知识就分享到这里。

二.pickle模块的作用及使用方法

pickle模块可以序列化和反序列化Python3对象,可将Python3对象与字节流相互转换,它与json区别如下:

  • json是一种文本序列化,它输出unicode文本,默认使用utf-8编码,而pickle是纯粹的二进制序列化。
  • json人类可读,而pickle二进制不易理解。
  • json在Python3生态系统之外广泛使用,而pickle只能在Python中使用。

pickle模块中也有dumps、loads、dump、load四个函数。

1.pickle模块中的dumps函数

dumps(obj,protocol = None)函数将任意对象编码后以bytes对象返回,参数obj是待序列化的Python3对象,protocol是pickler使用的协议版本,如果设置为True,则以高压缩的二进制格式保存序列化后的对象,否则以ASCII格式保存,为了节省空间和提高速度,我们一般将protocol设置为True。

2.pickle模块中的loads函数

loads(bytes_object,encoding =“utf-8”)将一个bytes对象反序列化为Python3对象并返回,encoding参数指定字节串的解码方式。

dumps函数序列化对象和loads函数反序列化字节串的代码如下。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# 模块说明板块
# =============================================================================
本文作者:安泽频道
抖音号码:anzechannel
快手号吗:anzechannel
联系邮箱:348834851@qq.com
创建日期:2021-11-23 21:52:36
编程软件:Win10专业版操作系统中Anaconda3虚拟的Python3.8环境中的spyder5.1.5
模块功能:Python3的pickle模块中dumps函数和loads函数的使用方法
import pickle
obj_anze = {
    "注意": "字典对象中的数据中尽量使用双引号,不要使用单引号",
    "name": "安泽频道",
    "contact": [
            "email": "348834851@qq.com",
            "multimedia": {
                "douyin": ["抖音号", "anzechannel"], "kuaishou":["快手号", "anzechannel"]
            "email": "anzechannel@qq.com",
            "multimedia": {
                "github": ["github号", "anzechannel"], "pypi":["pypi号", "anzechannel"]
# dumps函数将一个字典对象转化为字节对象
bytes_anze = pickle.dumps(obj_anze, protocol=True)
print('pickle.dumps函数将字典对象序列化后的字节串=', bytes_anze)
# 查看pickle.dumps函数返回值的类型
print('bytes_anze的数据类型是:', type(bytes_anze))
# loads函数将一个字节对象转化为字典对象
dict_anze = pickle.loads(bytes_anze, encoding='utf-8')
print('pickle.loads函数将字节串反序列化后的字典对象=', dict_anze)
# 查看pickle.loads函数返回值的类型
print('dict_anze的数据类型是:', type(dict_anze))

程序执行结果如下图所示。

dumps函数序列化对象和loads函数反序列化字节串的执行结果

3.pickle模块中的dump函数

dump(obj,file,protocol = None)函数将任意对象编码后写入文件,参数obj是待序列化的Python3对象,file是序列化后的字节串要写入的文件,protocol是pickler使用的协议版本,如果为True,则以高压缩的二进制格式保存序列化后的对象,否则以ASCII格式保存,为了节省空间和提高速度,我们一般将protocol设置为True。需要注意的是在序列化时我们最好使用二进制的方法写文件,如果以字符串的方式写文件则不同的操作系统会在文件添加不同的换行符或结束符,将会导致反序列化失败,而以二进制的方式写文件会保持原汁原味,能保证反序列化成功。dump函数将一个字典对象序列化至pickledump文件中的代码如下所示。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# 模块说明板块
# =============================================================================
本文作者:安泽频道
抖音号码:anzechannel
快手号吗:anzechannel
联系邮箱:348834851@qq.com
创建日期:2021-11-23 21:52:36
编程软件:Win10专业版操作系统中Anaconda3虚拟的Python3.8环境中的spyder5.1.5
模块功能:Python3的pickle模块中dump函数的使用方法
import pickle
obj_anze = {
    "注意": "字典对象中的数据中尽量使用双引号,不要使用单引号",
    "name": "安泽频道",
    "contact": [
            "email": "348834851@qq.com",
            "multimedia": {
                "douyin": ["抖音号", "anzechannel"], "kuaishou":["快手号", "anzechannel"]
            "email": "anzechannel@qq.com",
            "multimedia": {
                "github": ["github号", "anzechannel"], "pypi":["pypi号", "anzechannel"]
# dump函数将一个字典对象转化为字节对象后保存到文件pickledump中
# 打开文件时必须指定为wb,以二进制写文件
with open('pickledump', 'wb') as dump_file:
    pickle.dump(obj_anze, dump_file, protocol=True)
print('pickle.dump函数已将字典对象保存至pickledump文件中')

程序执行结果如下图所示。

dump函数将一个字典对象转化为字节对象后保存到文件pickledump

4.pickle模块中的load函数

load(file,encoding =“utf-8”)函数从打开的文件对象读取二进制字节并以指定的解码方式解码后将其反序列化成一个对象。load函数将一个文件对象反序列化为字典对象的代码如下所示。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# 模块说明板块
# =============================================================================
本文作者:安泽频道
抖音号码:anzechannel
快手号吗:anzechannel
联系邮箱:348834851@qq.com
创建日期:2021-11-23 21:52:36
编程软件:Win10专业版操作系统中Anaconda3虚拟的Python3.8环境中的spyder5.1.5
模块功能:Python3的pickle模块中load函数的使用方法
import pickle
# load函数将一个文件对象反序列化为一个字典对象
# 打开文件时必须指定为rb,以二进制写文件
with open('pickledump', 'rb') as load_file:
    load_anze = pickle.load(load_file, encoding='utf-8')
print('pickle.load函数已将pickledump文件对象反序列化为一个字典对象load_anze')
# 打印反序列化出来的字典对象load_anze中“注意”键的值
print('字典对象load_anze中“注意”键对应的值是:', load_anze["注意"])

程序执行结果如下图所示。

load函数将一个文件对象反序列化为字典对象

三.shelve模块的作用及使用方法

在已有json模块和pickle模块的情况下,为什么还要用shelve模块序列化数据?json模块和pickle模块能dump多次,但后面dump的数据会覆盖前面dump的数据,load只能获取到最后dump的数据,如果想要多次dump数据且不被覆盖,则可以使用shelve模块。

shelve模块是对pickle模块的封装,它实现了多次非覆盖式dump和多次load,可以当作一个简单的键值对数据库使用,它可以序列化任何pickle模块支持的数据格式,但是shelve模块中的key必需是字符串,而值可以是Python支持的任何数据类型。shelve访问己有key时,实际上是对原数据的拷贝,所以对拷贝做出的增删操作都需要使用writeback=True参数才能实现对原数据的修改。shelve只有一个open方法,打开文件后可以像字典一样使用get方法获取数据,shelve中dict[key]=data的操作,是存储数据的操作,若无对应的键名则新增一条键值对,若有对应的键名则覆盖已有的键值。shelve模块中序列化和反序列化的代码如下。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# 模块说明板块
# =============================================================================
本文作者:安泽频道
抖音号码:anzechannel
快手号吗:anzechannel
联系邮箱:348834851@qq.com
创建日期:2021-11-23 21:52:36
编程软件:Win10专业版操作系统中Anaconda3虚拟的Python3.8环境中的spyder5.1.5
模块功能:Python3的shelve模块的使用方法
import shelve
# shelve模块读取的文件有格式要求,所以一般shelve读取自己生成的文件。
# 不要使用shelve模块读取pickle模块或者其它模块生成的文件,会因为格式不匹配报错。
# shelve模块的open函数会生成3个文件shelvefile.bak、shelvefile.dat、shelvefile.dir。
# 其中shelvefile.dat中存储的是序列化后字节类型的数据,
# shelvefile.dat和shelvefile.dir中存储的是与数据缓存相关的东西。
# 注意:我们打开shelvefile文件的时候不需要后缀名,后缀名自动识别生成。
print('第一次使用open函数生成并打开shelvefile文件。')
with shelve.open('shelvefile') as shv_file:
    shv_file["name"] = '安泽频道'
    shv_file["QQ"] = 348834851
    shv_file["联系方式"] = ['douyin', 'anzechannel']
print('第一次关闭shelvefile文件。')
print('第二次使用open函数直接打开已存在的shelvefile文件并修改它。')
# 使用shelve.open函数将shelvefile文件反序列化为一个字典对象dict_anze01。
# 参数writeback=True可将我们的修改倒写至原文件中,以使修改持久化。
# 注意:我们打开shelvefile文件的时候不需要后缀名。
dict_anze01 = shelve.open('shelvefile', writeback=True)
# 获取字典对象dict_anze01中“联系方式”键的键值
print('字典对象dict_anze01中“联系方式”键对应的值是:', dict_anze01["联系方式"])
# 在字典对象dict_anze01中新增一个键值对并倒写至shelvefile文件
dict_anze01["新增列表"] = ['kuaishou', 'anzechanel']
print('在字典对象dict_anze01中增加的“新增列表”的键值为:', dict_anze01["新增列表"])
# 修改字典对象dict_anze01中“联系方式”键的键值
dict_anze01["联系方式"] = ['邮箱', '348834851@qq.com']
print('将字典对象dict_anze01中“联系方式”的值修改为:', dict_anze01["联系方式"])
# 关闭shelvefile文件
dict_anze01.close()
print('第二次关闭shelvefile文件。')
print('第三次使用open函数直接打开已存在的shelvefile文件并检查第二次的修改是否生效')
with shelve.open('shelvefile') as dict_anze02:
    # 获取修改后的联系方式
    print('修改后的联系方式是:', dict_anze02["联系方式"])
    # 获取增加的列表
    print('增加的列表是:', dict_anze02["新增列表"])
print('第三次关闭shelvefile文件。')

程序执行结果如下图所示。

shelve模块open函数序列化和反序列化的结果

四.struc模块的作用及使用方法

有时候需要用Python进行二进制数据处理,比如存取文件、Socket网络编程等,此时可以使用struct模块按照特定格式编码和解析二进制数据,特别适用于网络传输。struct模块中有3个重要的三个函数pack、unpack、 calcsize。

1.struct模块中的pack函数

pack(fmt, v1, v2, ...)函数按照给定的fmt格式,把v1, v2等数据封装成字节串,类似于c结构体中的字节流。

2.struct模块中的pack函数

unpack(fmt, bytes)函数按照给定的fmt格式解析字节流并将解析出的结果以元组形式返回。

3.struct模块中的pack函数

calcsize(fmt)函数计算给定的fmt格式占用多少字节的内存。

struct模块中序列化和反序列化的代码如下。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# 模块说明板块
# =============================================================================
本文作者:安泽频道
抖音号码:anzechannel
快手号吗:anzechannel
联系邮箱:348834851@qq.com
创建日期:2021-11-24 16:31:52
编程软件:Win10专业版操作系统中Anaconda3虚拟的Python3.8环境中的spyder5.1.5
模块功能:Python3的struct模块的calcsize函数、pack函数与unpack函数的使用方法
# =============================================================================
# 模块导入板块
# =============================================================================
import struct
# 定义多个变量
name = '安泽频道'.encode('utf-8')
level = 10
price = 168.68
# 计算12sif格式占用的字节数
print('calcsize函数计算出12sif格式占用的字节数是:', struct.calcsize('!12sif'))
# 使用pack函数以固定的12sif格式将上面3个变量序列化为一个字节串。
# 12sif是格式化字符串,由数字加字符构成,12s表示占12个字符的字符串,i表示1个整数。
# f表示1个浮点数,!表示使用网络字节顺序解析,因为在网络上传递的时候要用网络字节顺序。
bytes_array = struct.pack('!12sif', name, level, price)
print('pack函数序列化出的字节串是:', bytes_array)
# bytes_array已经是字节串,可以直接写入二进制文件binfile,
# 也可以使用socket.send(bytes_array)函数把字节串bytes_array通过套接字发送出去。
with open('binfile', 'wb') as write_file:
    write_file.write(bytes_array)