1 序列化
1.1 什么是序列化
将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。
|
序列:列表、元祖、字符串、bytes 序列化:字符串、bytes |
1.2 为什么要转成字符串?
能够在网络上传输的只能是bytes,
能够存储在文件里的只有bytes和str
|
序列化的目的 1、以某种存储形式使自定义对象持久化; 2、将对象从一个地方传递到另一个地方。 3、使程序更具维护性。
|

1.3 为什么要有序列化模块?
|
比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给? 现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。 但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。 你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢? 没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串, 但是你要怎么把一个字符串转换成字典呢? 聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。 eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。 BUT!强大的函数有代价。安全性是其最大的缺点。 想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。 而使用eval就要担这个风险。 所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构) s="{1:2}"
|
2 json模块—通用但限制多
Json模块提供了四个功能:dumps、dump、loads、load
|
# json # dumps loads # 在内存中做数据转换 : # dumps 数据类型 转成 字符串 序列化 (在内存中操作) # loads 字符串 转成 数据类型 反序列化 # dump load # 直接将数据类型写入文件,直接从文件中读出数据类型 # dump 数据类型 写入 文件 序列化 # load 文件 读出 数据类型 反序列化 # json是所有语言都通用的一种序列化格式 # 只支持 列表 字典 字符串 数字 # 字典的key必须是字符串 |
2.1 dumps和loads
dic = {'key' : 'value','key2' : 'value2'}
ret = json.dumps(dic) #序列化
print(dic,type(dic)) #{'key': 'value', 'key2': 'value2'} <class 'dict'>
print(ret,type(ret)) #{"key": "value", "key2": "value2"} <class 'str'>
res = json.loads(ret) #反序列化
print(res,type(res)) #{'key': 'value', 'key2': 'value2'} <class 'dict'>
2.1.1 问题一:
可以看到序列化和反序列化后key值的类型-----》字符串类型,
所以对于字典的约束: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.1.2 问题二:
dic = {1 : [1,2,3],2 : (4,5,'aa')}
ret = json.dumps(dic) # 序列化
print(dic,type(dic)) #{1: [1, 2, 3], 2: (4, 5, 'aa')} <class 'dict'>
print(ret,type(ret)) #{"1": [1, 2, 3], "2": [4, 5, "aa"]} <class 'str'>
res = json.loads(ret) # 反序列化
print(res,type(res)) #{'1': [1, 2, 3], '2': [4, 5, 'aa']} <class 'dict'>
|
2.1.3 问题三:
s = {1,2,'aaa'}
json.dumps(s) #TypeError
2.1.4 问题四:
json.dumps({(1,2,3):123}) #TypeError: keys must be a string
2.1.5 问题五:不支持连续的存 取
dic = {'key1' : 'value1','key2' : 'value2'}
with open('json_file','a') as f:
json.dump(dic,f)
json.dump(dic,f)
json.dump(dic,f)
with open('json_file','r') as f:
dic = json.load(f)
print(dic.keys())
2.1.6 常用于文件操作传输
#向文件中记录字典 dic = {'key' : 'value','key2' : 'value2'} ret = json.dumps(dic) with open('json_file','a') as f: f.write(ret) #从文件中读取字典 with open('json_file','r') as f: str_dic = f.read() di = json.loads(str_dic) print(di)
|
注意: json只能识别一个字典,如果多个字典在一行,当反序列化的时候就会报错,所以可以把字典放不同的行,并在读文件时,readline一行一行读
# 需求 :就是想要把一个一个的字典放到文件中,再一个一个取出来??? dic = {'key1' : 'value1','key2' : 'value2'}
with open('json_file','a') as f:
str_dic = json.dumps(dic)
f.write(str_dic+'\n')
str_dic = json.dumps(dic)
f.write(str_dic + '\n')
str_dic = json.dumps(dic)
f.write(str_dic + '\n')
with open('json_file','r') as f:
for line in f:
dic = json.loads(line.strip())
print(dic.keys())
|
2.2 结论:
|
# json 在所有的语言之间都通用 : json序列化的数据 在python上序列化了 那在java中也可以反序列化 # 能够处理的数据类型是非常有限的 : 字符串 列表 字典 数字 # 字典中的key只能是字符串 |
2.3 dump和load
dic = {'key1' : 'value1','key2' : 'value2'}
with open('json_file','a') as f:
json.dump(dic,f)
with open('json_file','r') as f:
dic = json.load(f)
print(dic)
|
结论:Dump和load直接操作文件 |
2.4 其他参数
data = {'username':['李华','二愣子'],'sex':'male','age':16}
json_dic2 = json.dumps(data,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False)
print(json_dic2)
结果:
{
"age":16,
"sex":"male",
"username":[
"李华",
"二愣子"
]
}
Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key ensure_ascii:,当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。) indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。 sort_keys:将数据根据keys的值进行排序。
3
pickle模块
|
用于序列化的两个模块 json,用于字符串 和 python数据类型间进行转换 pickle,用于python特有的类型 和 python的数据类型间进行转换 |
支持在python中几乎所有的数据类型
pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化)
3.1 特点:
(1)支持在python中几乎所有的数据类型
(2)dumps 序列化的结果只能是字节
(3)只能在python中使用
(4)在和文件操作的时候,需要用rb wb的模式打开文件
(5)可以多次dump 和 多次load
3.2 案例:
3.2.1 案例一:
import pickle dic = {(1,2,3):{'a','b'},1:'abc'} ret = pickle.dumps(dic) print(ret) #结果:b'\x80\x03}q\x00(K\x01K\........ #结论:dumps 序列化的结果只能是字节 print(pickle.loads(ret)) #{(1, 2, 3): {'b', 'a'}, 1: 'abc'}
3.2.2 案例二:
import pickle dic = {(1,2,3):{'a','b'},1:'abc'} with open('pickle_file','wb') as f: pickle.dump(dic,f) with open('pickle_file','rb') as f: ret = pickle.load(f) print(ret,type(ret)) #{(1, 2, 3): {'b', 'a'}, 1: 'abc'} <class 'dict'>
3.2.3 案例三:可以多次dump 和 多次load
dic = {(1,2,3):{'a','b'},1:'abc'}
dic1 = {(1,2,3):{'a','b'},2:'abc'}
dic2 = {(1,2,3):{'a','b'},3:'abc'}
dic3 = {(1,2,3):{'a','b'},4:'abc'}
with open('pickle_file','wb') as f:
pickle.dump(dic, f)
pickle.dump(dic1, f)
pickle.dump(dic2, f)
pickle.dump(dic3, f)
with open('pickle_file','rb') as f:
ret = pickle.load(f)
print(ret,type(ret))
ret = pickle.load(f)
print(ret,type(ret))
ret = pickle.load(f)
print(ret, type(ret))
ret = pickle.load(f)
print(ret, type(ret))
3.3 异常处理
with open('pickle_file','rb') as f: while True: try: ret = pickle.load(f) print(ret,type(ret)) except EOFError: break
浙公网安备 33010602011771号