Chow's Notes

pickle 模块、 json模块 序列化Python对象

序列化的概念很简单。内存里面有一个数据结构,你希望将它保存下来,重用,或者发送给其他人。

pickle 模块是Python标准库的一部分, 所以它总是可用的。它很快; 它的大部分同Python解释器本身一样是用C写的。 它可以存储任意复杂的Python数据结构。

pickle 协议是Python特定的,没有任何跨语言兼容的保证。你很可能不能使用Perl, php, Java, 或者其他语言来对你刚刚创建的entry.pickle文件做任何有用的事情。

最新版本的pickle协议是二进制格式的。请确认使用二进制模式来打开pickle文件,否则当你写入的时候数据会被损坏。

1.保存数据到 Pickle 文件

1
2
pickle.dump(entry, f)
entry = pickle.load(f)

2.序列化到一个内存中的bytes对象

1
2
b = pickle.dumps(entry)
entry3 = pickle.loads(b)

3.调试Pickle文件
pickletools.dis(f)

Python 3 在标准库中包含了一个json模块。同 pickle模块类似, json模块包含一些函数,可以序列化数据结构,保存序列化后的数据至磁盘,从磁盘上读取序列化后的数据,将数据反序列化成新的Pythone对象

首先, json数据格式是基于文本的, 不是二进制的。

由于是文本格式, 存在空白(whitespaces)的问题。 json 允许在值之间有任意数目的空白(空格, 跳格, 回车,换行)。

1.将数据保存至 json 文件

1
2
with open('basic.json', mode='w', encoding='utf-8')as f:
  json.dump(basic_entry, f)

json 是一个基于文本的格式, 这意味你可以以文本模式打开文件,并给定一个字符编码。用utf-8总是没错的。

2.序列化json不支持的数据类型

即使json没有内建的字节流支持, 并不意味着你不能序列化bytes对象。
json模块提供了编解码未知数据类型的扩展接口。(“未知”的意思是≴json没有定义”。
很显然json模块认识字节数组, 但是它被json规范的限制束缚住了。) 如果你希望编码字节串或者其它json没有原生支持的数据类型,你需要给这些类型提供定制的编码和解码器。

可以定义自己的“迷你序列化格式。”

1
2
3
4
5
6
7
def to_json(python_object):
if isinstance(python_object, bytes):
return {'__class__': 'bytes',
'__value__': list(python_object)}
raise TypeError(repr(python_object) + ' is not JSON serializable')
json.dump(entry, f,defaultcustomserializer.to_json)

3.从json文件加载数据

json.load()并不知道你可能传给json.dump()的任何转换函数的任何信息。你需要的是to_json()函数的逆函数 — 一个接受定制转换出的json 对象并将其转换回原始的Python数据类型。

1
2
3
4
5
6
7
8
9
10
def from_json(json_object):
if '__class__' in json_object:
if json_object['__class__'] == 'time.asctime':
return time.strptime(json_object['__value__'])
if json_object['__class__'] == 'bytes':
return bytes(json_object['__value__'])
return json_object
with open('entry.json', 'r', encoding='utf-8') as f:
entry = json.load(f,object_hook=from_json)

json 并不区分元组和列表;它只有一个类似列表的数据类型,数组,并且json模块在序列化过程中会安静的将元组和列表两个都转换成json 数组。大多数情况下,你可以忽略元组和列表的区别,但是在使用json模块时应记得有这么一回事.

很多关于pickle模块的文章提到了cPickle。
在Python 2中, pickle模块有两个实现,
一个由纯Python写的而另一个用C写的(但仍然可以在Python中调用)。在Python 3中, 这两个模块已经合并, 所以你总是简单的import pickle就可以。