序列化:从数据类型---->字符串的过程
反序列化:从字符串----->数据类型的过程
使用场景:
1.数据存储和提取
2.网络传输的时候
序列化模块:
1.json 重要指数:五星
特点:
①通用的序列化格式
②只有很少的一部分数据类型能够通过jason转化成字符串
2.pickle 重要指数:四星
特点:
①所有的python中的数据类型都可以转化成字符串形式
②pickle序列化的内容只有python能理解
③部分反序列化依赖python代码
3.shelve 重要指数:三星
特点:
①序列化句柄
②使用句柄直接操作,非常方便
方法:
json 适用的数据类型:数字、字符串、列表、字典、元组(元组是转换成列表进行序列化)
dumps 序列化方法 loads 反序列化方法
这是在内存中将数据进行序列化和反序列化操作,数据还在内存中。
import json dic = {'k1':'v1','k2':'v2','k3':'v3'} str_dic = json.dumps(dic) #序列化:将一个字典转换成一个字符串 print(type(str_dic),str_dic) #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"} #注意,json转换完的字符串类型的字典中的字符串是由""表示的 dic2 = json.loads(str_dic) #反序列化:将一个字符串格式的字典转换成一个字典 #注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示 print(type(dic2),dic2) #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}] str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型 print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}] list_dic2 = json.loads(str_dic) print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}] loads和dumps
dump 和 load 对文件进行操纵,直接把数据类型序列化后存储,和反序列化的提取数据类型
import json f = open('json_file','w') dic = {'k1':'v1','k2':'v2','k3':'v3'} json.dump(dic,f) #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件 f.close() f = open('json_file') dic2 = json.load(f) #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回 f.close() print(type(dic2),dic2) load和dump
编码中文的问题 ,在dumps和dump ensure_ascii 加上就能在文件中显示中文,否则是bytes类型显示在文件中,但是并不影响存储和提取
import json f = open('file','w') json.dump({'国籍':'中国'},f) ret = json.dumps({'国籍':'中国'}) f.write(ret+'\n') json.dump({'国籍':'美国'},f,ensure_ascii=False) ret = json.dumps({'国籍':'美国'},ensure_ascii=False) f.write(ret+'\n') f.close() ensure_ascii关键字参数
dump和load在文件中的操作只能是一次性的,多次写就不能load,报错,利用dumps和loads解决多行存取的问题
import json l = [{'k': '111'},{'k2': '111'}, {'k3': '111'}] f = open('file', 'w') for dic in l: str_dic = json.dumps(dic) f.write(str_dic+'\n') f.close() f = open('file') l = [] for line in f: dic = json.loads(line.strip()) l.append(dic) f.close() print(l)
pickle
pickle模块提供了四个功能:dumps、dump(序列化,存)、loads(反序列化,读)、load (不仅可以序列化字典,列表...可以把python中任意的数据类型序列化)
dumps和loads是针对内存当中的数据类型进行序列化
dump和load是针对文件当中的存取
dumps 和 loads >>> import pickle >>> dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} >>> pickle.dumps(dic) # bytes类型 b'\x80\x03}q\x00(X\x02\x00\x00\x00k1q\x01X\x02\x00\x00\x00v1q\x02X\x02\x00\x00\x00k2q\x03X\x02\x00\x00\x00v2q\x04X\x02\x00\x00\x00k3q\x05X\x02\x00.' >>> dic1 = pickle.dumps(dic) >>> pickle.loads(dic1) # 转成字典类型 {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} dump 和 load import pickle dic = {'k1': '中国', 'k2': 'v2', 'k3': 'v3'} f = open('fff', 'wb') # 写的时候需要用b模式 pickle.dump(dic, f) # 多次写 pickle.dump(dic, f) f.close() f = open('fff', 'rb') # load的时候需要用b模式 同时可以多次写,同等次数的读,次数不同会漏 data = pickle.load(f) data1 = pickle.load(f) f.close() print(data, data1)
json & pickle
相同的地方:都有dumps、loads、dump、load四个方法
不同的地方:
json:跨语言,通用型,只支持数字、字符串、列表、元组、字典数据类型的序列化操作,体积小
pickle:支持python所有数据类型的序列化操作,占内存,dump和load的时候必须是在b的模式下。
使用:如果你序列化的内容是列表或者字典,我们非常推荐你使用json模块;但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle
shelve
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式
shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。
shelve.open(filename, flag='c', protocol=None, writeback=False) # 4个参数
import shelve f = shelve.open('shelve_test') # 打开一个文件 names = ["alex", "rain", "test"] info = {'name':'alex','age':22} f["names"] = names # 持久化列表 f['info_dic'] = info f.close()
import shelve f1 = shelve.open('shelve_file') existing = f1['names'] #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错 f1.close() print(existing)
这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB
import shelve f = shelve.open('shelve_file', flag='r') existing = f['key'] f.close() print(existing)
由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。
import shelve f1 = shelve.open('shelve_file') # 此时修改不能保存 print(f1['key']) f1['key']['new_value'] = 'this was not here before' f1.close() f2 = shelve.open('shelve_file', writeback=True) # 修改保存 print(f2['key']) f2['key']['new_value'] = 'this was not here before' f2.close()
writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。