json 模块 和 pickle
一. 序列化
什么叫序列化
在python中将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。
将字符串转换成列表,字典的过程叫做反序列化。
比如,我们在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、使程序更具维护性。
二. json 模块
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写。
函数 | 描述 |
---|---|
json.dumps | 将 Python 对象编码成 JSON 字符串 |
json.loads | 将已编码的 JSON 字符串解码为 Python 对象 |
#json
# dumps loads
#只在内存中做数据转换
#dumps 数据类型转成字符串 序列化
#loads 字符串转成数据类型 反序列化
# dump load
#直接将数据类型写入文件,直接从文件中读出数据类型
#dump 数据类型 写入文件 序列化
#load 文件读出数据 反序列化
# json 是所有语言都通用的一种序列化格式
# 只支持 列表 字典 字符串 数字
# 字典的key 必须是字符串
import json ret = json.dumps(dic) #序列化 print(ret, type(ret)) print(dic, type(dic)) res = json.loads(ret) # 反序列化 print(res, type(res)) {"key": "value", "key2": "value2"} <class 'str'> #会发现json字符串中的引号都变成了双引号了,这是由于json是有固定的语法格式的,我们在读取json字符串时,需要json字符串遵循固有的语法格式。 {'key': 'value', 'key2': 'value2'} <class 'dict'> {'key': 'value', 'key2': 'value2'} <class 'dict'>
import json f = open('json_file', 'w') dic = {'key': 'value', 'key2': 'value2'} json.dump(dic, f) f2 = open('json_file', 'r') print(json.load(f2))
三. pickle模块
由于使用json进行序列化,有诸多限制,需要遵循json的语法规则,如果不涉及跨语言的数据交换,可以使用pickle来进行序列化和反序列化。
json进行序列化后得到的结果是字符串,而pickle序列化之后得到的bytes数据类型。
dumps 和 loads
序列化:
import pickle, json dic = {'key': 'value', 'key2': 'value2'} json_ret = json.dumps(dic) pickle_ret = pickle.dumps(dic) print(type(json_ret),json_ret) print(type(pickle_ret),pickle_ret) <class 'str'> {"key": "value", "key2": "value2"} <class 'bytes'> b'\x80\x03}q\x00(X\x03\x00\x00\x00keyq\x01X\x05\x00\x00\x00valueq\x02X\x04\x00\x00\x00key2q\x03X\x06\x00\x00\x00value2q\x04u.'
反序列化:
dic = {'key': 'value', 'key2': 'value2'} json_ret = json.dumps(dic) pickle_ret = pickle.dumps(dic) # print(type(json_ret), json_ret) # print(type(pickle_ret), pickle_ret) ret_json = json.loads(json_ret) ret_pickle = pickle.loads(pickle_ret) print(ret_json) print(ret_pickle) #{'key': 'value', 'key2': 'value2'} #{'key': 'value', 'key2': 'value2'}
dump 和 load
dic = {'key': 'value', 'key2': 'value2'} f = open('pickle_file', 'wb') # 由于pickle序列化后是bytes类型,所以写入需要使用mode+b的模式打开文件。 pickle.dump(dic, f) f.close() f2 = open('pickle_file', 'rb') ret = pickle.load(f2) print(ret) #{'key': 'value', 'key2': 'value2'}
总结:json可以用于各种不同语言中的数据交换,各种语言都遵循json的语法格式,所以json对于数据处理是相对严格的,如果不用于数据交换,只为了数据持久化,可以考虑使用pickle,pickle在python中可以序列化几乎所有的数据类型,而且没有json那样的语法限制,后期会有较多其他的使用场景,后期如果有用到在进行补充。