欢迎来到Louis的博客

人生三从境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
扩大
缩小

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那样的语法限制,后期会有较多其他的使用场景,后期如果有用到在进行补充。

posted on 2018-08-21 21:50  Louiszj  阅读(84)  评论(0编辑  收藏  举报

导航