参考博客:http://www.cnblogs.com/yyds/p/6563608.html
json.dumps() | 将python数据类型转换为(json)字符串 |
json.loads() | 将json字符串转化为python数据类型 |
json.dump() | 将python数据类型以json形式保存在本地磁盘 |
json.load() | 将本地磁盘中的json数据转化为python数据类型 |
pickle.dumps() | 将python数据类型转化为python特定的二进制格式 |
pickle.loads() | 将特定的二进制格式转化为python数据类型 |
pickle.dump() | 将python数据类型以特定的二进制格式保存到磁盘 |
pickle.load() | 将本地磁盘中python特定的二进制格式数据转化为python数据类型 |
shelve.open() | 以类型dict的形式将python数据类型保存到本地磁盘或读取本地磁盘数据并转化为python数据类型 |
一、序列化概论
每种编程语言都有各自的的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),python也是一样。
很多时候,我们需要把各种数据类型的数据通过网络传送给其它机器或客户端,或者想把内层中的各种数据类型的数据保存到本地磁盘持久化。
而我们知道文件中存储的都是字符串,因此就需要格式的转化。
如果要将一个系统内的数据通过网络传输给其它系统或客户端,
我们通常都需要先把这些数据转化为字符串或字节串,
而且需要规定一种统一的数据格式才能让数据接收端正确解析并理解这些数据的含义。
XML是早期被广泛使用的数据交换格式,而如今大家使用更多的数据交换格式是JSON(JavaScript Object Notation),
它是一种轻量级的数据交换格式。JSON相对于XML而言,更加简单、易于阅读和编写,同时也易于机器解析和生成。
如果想把数据持久化到本地磁盘,这部分数据通常只是供系统内部使用,
因此数据转换协议以及转换后的数据格式也就不要求是标准、统一的,只要本系统内部能够正确识别即可。
将对象转换为可通过网络传输或可以存储到本地磁盘的数据格式的过程称为序列化;反之,则称为反序列化。
在python中有几个内置的用于数据序列化的模块。
模块名称 | 描述 | 提供的api |
json | 用于实现python数据类型与通用(json)字符串之间的转换 | dumps()、dump()、loads()、load() |
pickle | 用于实现python数据类型与python特定二进制格式之间的转换 | dumps()、loads() |
shelve | 专门用于将python数据类型的数据持久化到磁盘,shelve是一个类似dict的对象。 | open() |
二、json模块
>>> import json >>> data = {"name":"kebi","age":25} >>> in_json = json.dumps(data) >>> type(in_json) #序列化:将一个字典转化为字符串 <class 'str'> >>> in_json '{"name": "kebi", "age": 25}' >>> json.loads(in_json) {'name': 'kebi', 'age': 25} >>> out_json = json.loads(in_json) #反序列化:将一个字符串格式的字典转化为字符串 >>> out_json {'name': 'kebi', 'age': 25} >>> type(out_json) <class 'dict'> #字典格式
除此之外,json模块还提供了两个额外的方法允许我们直接将序列化后得到的json数据保存到文件中,以及直接读取文件中的json数据进行反序列化操作。
>>> f = open('json_file','w') >>> data {'name': 'kebi', 'age': 25} >>> json.dump(data,f) #dump方法接受一个文件句柄,直接将字典转化为json字符串写入文件 >>> f.close() [root@7 tmp]# cat json_file {"name": "kebi", "age": 25} #已经写入 >>> f = open('json_file') >>> data2 = json.load(f) #load方法接受一个文件句柄,直接将文件中的json字符串转化成数据结构返回。 >>> data2 {'name': 'kebi', 'age': 25} >>> type(data2) <class 'dict'> #返回的是列表
在进行数据格式转换的时候,数据的类型会略有改动。
>>> json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}) '{"a": "str", "c": true, "e": 10, "b": 11.1, "d": null, "f": [1, 2, 3], "g": [4, 5, 6]}'
由上可知,True变成true,列表和元祖都变成序列,None变为null等
>>> json.loads('{"a": "str", "c": true, "b": 11.1, "e": 10, "d": null, "g": [4, 5, 6], "f": [1, 2, 3]}') {'c': True, 'e': 10, 'a': 'str', 'g': [4, 5, 6], 'd': None, 'f': [1, 2, 3], 'b': 11.1}
在反序列化的时候部分又会变回来。
三、pickle模块
pickle模块实现了用于对python对象结构进行序列化和反序列化的二进制协议。
>>> import pickle >>> data {'name': 'kebi', 'age': 25} >>> str_data = pickle.dumps(data) >>> str_data b'x80x03}qx00(Xx04x00x00x00nameqx01Xx04x00x00x00kebiqx02Xx03x00x00x00ageqx03Kx19u.' >>> data3 = pickle.loads(str_data) >>> data3 {'name': 'kebi', 'age': 25}
pickle模块和json模块对比:
(1)JSON是一种文本序列化格式(它输出的是unicode文件,大多数时候会被编码为utf-8),而pickle是一个二进制序列化格式。json我们能够读懂,而pickle不行。
(2) JSON是与特定的编程语言无关,且它在python之外被广泛使用,而pickle使用的数据格式是特定于python的。
(3)默认情况下,JSON只能表示python内建数据类型,pickle可以直接表示大量的python数据类型。
四、shelve模块
shelve是一个简单的数据存储方案,类似于key-value数据库,可以很方便的保存python对象,其内部是通过pickle协议来实现数据序列化。
>>> import shelve >>> f = shelve.open('shelve_file') #直接对文件句柄进行操作,就可以存入数据 >>> f['key'] = {'name': 'kebi', 'age': 25} >>> f.close() >>> import shelve >>> f1 = shelve.open('shelve_file') #取出数据的时候也只需直接用key获取即可,但是如果key不存在就会报错。 >>> existing = f1['key'] >>> f1.close() >>> existing {'name': 'kebi', 'age': 25}
总结:
(1)各自优缺点
json模块常用于编写web接口,将python数据转化为通用的json格式传递给其它系统或客户端;
也可以用于将python数据保存到本地文件中,缺点是明文保存,保密性差。
pickle模块和shelve模块由于使用其特有的序列化协议,其序列化之后的数据只能被python识别,因此只能用于系统内部。
同时python2和python3默认使用的序列协议也不同,需要兼容的话还需要指定协议的版本。
pickle模块和shelve模块相对于json来说,对于自定义数据类型可以直接序列化和反序列化,不需要编写额外的转换函数或类。
shelve模块可以看作是pickle模块的升级版,因为shelve使用的就是pickle的序列化协议,
但是shelve比pickle提供的操作方式更加简单、方便。
shelve模块相对于其它两个模块在将python数据持久化到本地磁盘时有一个很明显的优点就是,
它允许我们可以像操作dict一样操作被序列化的数据,而不必一次性的保存或读取所有的数据。
(2)适用场景
在与外部系统交接互用时用json模块。
需要将少量、简单python数据持久化到本地磁盘文件时可以考虑用pickle模块。
需要将大量python数据化持久到本地磁盘文件或需要一些简单的类似数据库的增删改查功能时,可以考虑用shelve模块。