首页 > 代码库 > python开发模块基础:序列化模块json,pickle,shelve

python开发模块基础:序列化模块json,pickle,shelve

一,为什么要序列化

# 将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化
‘‘‘
比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?
现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。
但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。
你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?
没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串,
但是你要怎么把一个字符串转换成字典呢?
聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。
eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
BUT!强大的函数有代价。安全性是其最大的缺点。
想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。
而使用eval就要担这个风险。
所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)
‘‘‘
# 序列化的目的
# 1、以某种存储形式使自定义对象持久化;
# 2、将对象从一个地方传递到另一个地方。
# 3、使程序更具维护性。
# 数据结构 --> 序列化 --> str
# str --> 反序列化 --> 数据结构

 

二,json模块

json 不是python发明的,所有的语言都在用,语言之间用字符串传递
json 字符串 字典 列表可以的
json 模块提供四个功能:dumps,dump,loads,load

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 
 4 #字典转化为字符串
 5 import json
 6 ret_s = json.dumps(d)
 7 print(ret_s,type(ret_s))
 8 
 9 #字符串转化为字典
10 ret_d = json.loads(ret_s)
11 print(ret_d,type(ret_d))
12 
13 #注意字符串必须是一个双引号,单引号就会报错
14 f = open(json_file)
15 d_s = f.read()
16 print(json.loads(d_s))
17 f.close()
18 
19 # 小结   内存操作
20 #dumps  结构化的数据类型转字符串
21 #loads  字符串转结构化数据类型  结构化数据类型中的所有字符串必须是双引号引用
22 
23 # 写回文件 dump load 操作文件跟序列化的关系
24 f = open(json_file,w)
25 dic = {k1:v1,k2:v2,k3:v3}
26 json.dump(dic,f)     #f就是文件句柄,直接就是把dic写入文件里
27 # f.write(json.dumps(dic))  #是先dumps转成字符串在写入文件
28 f.close()
29 
30 f = open(json_file)
31 dic2 = json.load(f)  #直接告诉文件是什么
32 print(dic2,type(dic2)) #直接就是一个字典类型,不需要转化
33 f.close()

 

三,pickle模块

所有数据类型都可以,但是只是Python自有的,而且是bytes(用于一种Python独特状态)

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 
 4 # json & pickle模块
 5 # 用于序列化的两个模块
 6     # json,用于字符串 和 python数据类型间(列表,字典)进行转换
 7     # pickle,用于python特有的类型 和 python的数据类型间进行转换
 8 
 9 # pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load  (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化)
10 # python 特有的元祖  会被json搞成列表
11 # set               json不支持
12 tu = {1,2,3,4}
13 # import json
14 # print(json.dumps(tu))  #json不支持,所以这里不支持
15 import pickle
16 print(pickle.dumps(tu))    #bytes类型
17 pik_b = pickle.dumps(tu)
18 print(pickle.loads(pik_b)) #转回来

 

四,shelve模块

shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些。
shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 
 4 import shelve
 5 f = shelve.open(shelve_file)
 6 f[key] = {int:10, float:9.5, string:Sample data}  #直接对文件句柄操作,就可以存入数据
 7 f.close()
 8 
 9 import shelve
10 f1 = shelve.open(shelve_file)
11 existing = f1[key]  #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错
12 f1.close()
13 print(existing)
14 
15 #注意:这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。
16 # 所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB
17 import shelve   #只读模式,就不会影响写的人了
18 f = shelve.open(shelve_file, flag=r)
19 existing = f[key]
20 f.close()
21 print(existing)
22 
23 #注意:由于shelve在默认情况下是不会记录待持久化对象的任何修改的,
24 # 所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。
25 import shelve
26 f1 = shelve.open(shelve_file)  #没有改
27 print(f1[key])
28 f1[key][new_value] = this was not here before
29 f1.close()
30 
31 f2 = shelve.open(shelve_file, writeback=True)  #改了
32 print(f2[key])
33 f2[key][new_value] = this was not here before
34 f2.close()
35 
36 # 小结:writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;
37 # 但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,
38 # 并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。
39 # 因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。

 

python开发模块基础:序列化模块json,pickle,shelve