Python 20 json、pickle、shelve序列化模块
序列化模块 |
什么是序列化------>将原本的字典、列表等内容转换成字符串的过程叫做序列化
为什么要序列化
数据存储
网络上传输的时候
从数据类型---> 字符串的过程 序列化
从字符串 -----> 数据类型的过程 反序列化
序列化模块有三种:json pickle shelve
json:
通用的序列化格式
只有很少一部分数据类型能够通过json转化为字符串
json转化的字符串最直观的能看懂
pickle:
所有的python中的数据类型都可以转化成字符串形式
pickle序列化的内容只有python能理解
且部分反序列化依赖代码
shelve:
序列化句柄
使用句柄直接操作,非常方便
jsos 有四种方法:dumps loads dump load
dumps是序列化方法,loads是反序列化方法。都是对内存直接操作的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
dic = {'k1':'v1'} json dumps序列化方法 loads反序列化方法 : 对内存操作 print(type(dic),dic) import json str_d = json.dumps(dic) print(type(str_d),str_d) dic_d = json.loads(str_d) print(type(dic_d),dic_d)
可以序列化的数据类型有:数字 字符串 列表 字典 元组(转成列表) 其他不行
json dump load :对文件操作
|
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json dic = {'a':1,'b':2} f = open('fff','w',encoding='utf-8') json.dump(dic,f) f.close() f = open('fff') res = json.load(f) f.close() print(res,type(res))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json dic = {'a':'中国','b':'国家'} f = open('fff','w',encoding='utf-8') json.dump(dic,f,ensure_ascii=False) # 这里加一个 ensure_ascii=False f.close() f = open('fff',encoding='utf-8') res = json.load(f,) f.close() print(res,type(res))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json l = [{'k':111},{'k':111},{'k':111}] f = open('file','w') for dic in l: str_dic = json.dumps(dic) f.write(str_dic+'\n') f.close() l = [] f = open('file') for line in f: dic = json.loads(line.strip()) l.append(dic) f.close() print(l)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Serialize obj to a JSON formatted str.(字符串表示的json对象) 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的中文即可正常显示。) If check_circular is false, then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse). If allow_nan is false, then it will be a ValueError to serialize out of range float values (nan, inf, -inf) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (NaN, Infinity, -Infinity). indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。 default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError. sort_keys:将数据根据keys的值进行排序。 To use a custom JSONEncoder subclass (e.g. one that overrides the .default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json data = {'username':['李华','二愣子'],'sex':'male','age':16} json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False) print(json_dic2)
pickle dumps loads dump load |
可以任意类型,但反序列化也要这个代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pickle dic = {'k1':'v1','k2':'v2','k3':'v3'} str_dic = pickle.dumps(dic) print(str_dic) # 一串二进制内容 dic2 = pickle.loads(str_dic) print(dic2) # 字典 import time struct_time = time.localtime(1000000000) print(struct_time) f = open('pick_file','wb') pickle.dump(struct_time,f) f.close() f = open('pick_file','rb') struct_time2 = pickle.load(f) print(struct_time2.tm_year) f.close()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time struct_time1 = time.localtime(1000000000) struct_time2 = time.localtime(2000000000) # print(struct_time) f = open('pick_file','wb') pickle.dump(struct_time1,f) pickle.dump(struct_time2,f) f.close() f = open('pick_file','rb') struct_time3 = pickle.load(f) struct_time4 = pickle.load(f) print(struct_time3.tm_year) print(struct_time4.tm_year) f.close()
shelve |
shelve也是python提供给我们的序列化工具,比pickle用起来简单一些
shelve也只提供了一个open的方法,是用key来访问的,使用起来和字典类似
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import shelve f = shelve.open('shelve_file') f['key'] = {'int':10,'float':9.5,'string':'sample data'} # 直接对文件句柄操作,就可以修改数据 f.close() import shelve f1 = shelve.open('shelve_file') existing = f1['key'] # 取出数据时,只需要直接用key获取即可,但是如果key不存在,会报错 f1.close() print(existing)
这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们就让
shelve通过只读方式打开DB
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
第一种 import shelve f = shelve.open('shelve_file',flag='c') existing = f['key'] f.close() print(existing) 第二种 import shelve f = shelve.open('shelve_file',flag='r') existing = f['key'] f['key'] = 10 # 这样就把key的值全改了 f.close() print(existing) f = shelve.open('shelve_file',flag='r') existing2 = f['key'] f.close() print(existing2)
由于shelve在默认情况下是不会记录待持久化对象的任何修改,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import shelve f1 = shelve.open('shelve_file') print(f1['key']) f1['key']['new value'] = 'this was not here before' f1.close() import shelve f1 = shelve.open('shelve_file',writeback=True) print(f1['key']) f1['key']['new value'] = 'this was not here before' f1.close()
writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明;但这种并不是所有的情况下都需要,首先,使用writeback以后,shelve在open()时候会额外的增加内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有被修改,因此所有的对象都会被写入