一、题外话
序列化:把其他数据类型转换成字符串或者bytes的过程
为什么要使用序列化
1. 在网络上传输的只能是bytes
2. 存储在文件中的只能是字符串和bytes
二、json模块
tips1:json模块能够处理的数据类型是非常有限的,仅仅包括:字典、字符串、列表、数字
tips: json模块之所以有这么多的限制,是因为json模块是所有语言都通用的,不止是我们python在用,所系必须是规范化的,简单来说,比如我们用python使用json序列化了一个字符串,那在java中,也能反序列化回去继续使用,反之亦然。
json模块提供了4个方法,下面依次介绍:
1. json.dumps 序列化(在内存中操作)
import json
dic = {"name": "HYG", "age": 18}
result = json.dumps(dic) # dumps:序列化
print(result, type(result)) # {"name": "HYG", "age": 18} <class 'str'>
字典在序列化后,得到的字符串结果是"",不是’’
2. json.loads 反序列化(在内存中操作)
import json
dic = {"name": "HYG", "age": 18}
result = json.dumps(dic) # dumps:序列化
result1 = json.loads(result) # loads:反序列化
print(result, type(result)) # {"name": "HYG", "age": 18} <class 'str'>
print(result1, type(result1)) # {'name': 'HYG', 'age': 18} <class 'dict'>
3. json.dump 序列化(操作文件),序列化之后,直接存到文件中
dic = {"name": "HYG", "age": 18}
with open("test.txt", "a") as file:
json.dump(dic, file) # 直接把该字典序列化之后,存到文件中
# 文件内容:{"name": "HYG", "age": 18}
4. json.loads 反序列化(操作文件),把文件中的内容反序列化后为我们所用
with open("test.txt") as file:
ret = json.load(file)
print(ret, type(ret)) # {'name': 'HYG', 'age': 18} <class 'dict'>
原文件内容就是我们之前序列化过得字符串
tips:我们可以在文件中手动添加内容,反序列化也可以得到,但是:我们手动添加的字符串内容,字符串内容,必须用""双引号,单引号是会报错的
5. 由于题开始就阐述了json的各种约束,所以,json使用的时候,会遇到一些问题,下面是遇到的一些问题,总结归纳了一下:
①、当把数字作为字典key时:
- 把数字作为兼职对的key的时候,序列化的时候是没有问题可以直接操作的,但是反序列化回来后,我们之前的数字,就变成字符串格式啦
②、当把元组作为字典的value时:
- 把元组作为字典的value去处理的时候,一样的,序列化的时候把元组改成了列表,反序列化回来之后,我们的元组,也被强行改成了列表!!!
③、如果:
- 字典的key是元组、序列化的对象是集合或元组或其他情况下,
是不能进行序列化哒!!!
# 问题1:数字做key的问题
dic = {1: 'value', 2: 'value2'}
ret = json.dumps(dic) # 序列化
print(dic, type(dic)) # {1: 'value', 2: 'value2'} <class 'dict'>
print(ret, type(ret)) # {"1": "value", "2": "value2"} <class 'str'>
res = json.loads(ret) # 反序列化
print(res, type(res)) # {'1': 'value', '2': 'value2'} <class 'dict'>
# 问题2
dic1 = {1: [1, 2, 3], 2: (4, 5, 'aa')}
ret1 = json.dumps(dic1) # 序列化
print(dic1, type(dic1)) # {1: [1, 2, 3], 2: (4, 5, 'aa')} <class 'dict'>
print(ret1, type(ret1)) # {"1": [1, 2, 3], "2": [4, 5, "aa"]} <class 'str'>
res1 = json.loads(ret1) # 反序列化
print(res1, type(res1)) # {'1': [1, 2, 3], '2': [4, 5, 'aa']} <class 'dict'>
6. 小扩展
dic = {"name": "张三丰"}
print(json.dumps(dic)) # {"name": "\u5f20\u4e09\u4e30"}
print(json.dumps(dic, ensure_ascii=False)) # {"name": "张三丰"}
tips:除了ensure_ascii,还有很多这些参数,可以控制我们的输出,使输出更好看,详见博客:
三、pickle模块
pickle模块和json模块做的事情差不多是一样的
所提供的方法也是一样的,dumps,loads,dump,load
pickle的特点:
1.pickle模块几乎可以处理所有的数据类型
2. 但是只能在python中使用
3. 它可以多次dumps和loads
4. 他dumps后的数据类型只能是bytes
yz = (1, 2, 3)
result = pickle.dumps(yz)
print(result) # b'\x80\x03K\x01K\x02K\x03\x87q\x00.'
result1 = pickle.loads(result)
print(result1) # (1, 2, 3)
使用dump和load方法打开文件时,必须使用wb和rb方法打开文件,不然会报错:TypeError: write() argument must be str, not bytes
with open("test1.txt", "wb") as file:
pickle.dump(yz, file) # 文件内容:�KKK�q . 由于是bytes格式,使用utf-8格式就是这样的乱码
with open("test1.txt", "rb") as file1:
print(pickle.load(file1)) # (1, 2, 3)