status |
草稿 |
清风 & Liz; 100% |
Contents
PCS210 pickle
概述
pickle模块可以实现任意的Python对象的序列化.这些序列化后的对象可以被传输或存储,也可以重构为一个和原先对象具有相同特征的新对象。但在实际项目中为了提高序列化和反序列化的速度,可以改用cPickle模块.pickle的文档清晰的表明它不提供安全保证。所以慎用pickle来作为内部进程通信或者数据存储,也不要相信那些你不能验证安全性的数据。
使用
第一个pickle示例是将一个数据结构编码为一个字符串,然后将其输出到控制台。
1 try:
2 import cPickle as pickle
3 except:
4 import pickle
5 import pprint
首先尝试导入cPickle,并指定别名为"pickle"。如果因为某种原因导入pickle失败,则导入由Python实现的pickle模块。这样,如果cPickle可用则速度会快点,但如果不可用,也会有正确的实现。接下来,定义一个完全由基本类型组成的数据结构。
1 data = [ { 'a':'A', 'b':2, 'c':3.0 } ]
2 print 'DATA:',
3 pprint.pprint(data)
可以使用pickle.dumps()来创建数据值的字符串表示。
1 data_string = pickle.dumps(data)
2 print 'PICKLE:', data_string
可以看到结果如下:
~$ python pcs-201-1.py
DATA:[{'a': 'A', 'b': 2, 'c': 3.0}]
PICKLE: (lp1
(dp2
S'a'
S'A'
sS'c'
F3
sS'b'
I2
sa.
一旦数据被序列化,就可以把他写入到文件、socket、管道等等中。之后你可以读取这个文件,读取这些数据来构造具有相同值的新对象。
1 # -*- coding: utf-8 -*-
2 data1 = [ { 'a':'A', 'b':2, 'c':3.0 } ]
3 print 'BEFORE:',
4 pprint.pprint(data1)
5
6 data1_string = pickle.dumps(data1)
7
8 data2 = pickle.loads(data1_string)
9 print 'AFTER:',
10 pprint.pprint(data2)
11
12 print 'SAME?:', (data1 is data2)
13 print 'EQUAL?:', (data1 == data2)
新构造的对象等于原来的对象,但他们又不是相同的对象。
~$ python pcs-201-2.py
BEFORE:[{'a': 'A', 'b': 2, 'c': 3.0}]
AFTER:[{'a': 'A', 'b': 2, 'c': 3.0}]
SAME?: False
EQUAL?: True
在处理自定义类时,应该保证这些被序列化的类会在进程名空间出现 。只有数据实例才能被序列化,而不能是定义的类。在反序列化时,类的名字被用于寻找构造器以便创建新对象。接下来这个例子,是将一个类实例写入到文件中:
1 # -*- coding: utf-8 -*-
2 try:
3 import cPickle as pickle
4 except:
5 import pickle
6 import sys
7
8 class SimpleObject(object):
9
10 def __init__(self, name):
11 self.name = name
12 l = list(name)
13 l.reverse()
14 self.name_backwards = ''.join(l)
15 return
16
17 if __name__ == '__main__':
18 data = []
19 data.append(SimpleObject('pickle'))
20 data.append(SimpleObject('cPickle'))
21 data.append(SimpleObject('last'))
22
23 try:
24 filename = sys.argv[1]
25 except IndexError:
26 raise RuntimeError('Please specify a filename as an argument to %s' % sys.argv[0])
27
28 out_s = open(filename, 'wb')
29 try:
30 # 写入到流中
31 for o in data:
32 print 'WRITING: %s (%s)' % (o.name, o.name_backwards)
33 pickle.dump(o, out_s)
34 finally:
35 out_s.close()
当运行这个脚本时,它会创建名为命令行中输入参数的文件:
~$ python pcs-201-3.py test.dat WRITING: pickle (elkcip) WRITING: cPickle (elkciPc) WRITING: last (tsal)
一个简单的尝试是将刚才的序列化对象装载进来,如下:
1 # -*- coding: utf-8 -*-
2 try:
3 import cPickle as pickle
4 except:
5 import pickle
6 import pprint
7 from StringIO import StringIO
8 import sys
9 #注意:需要导入自定义类
10 from pcs-201-3 import SimpleObject
11
12 try:
13 filename = sys.argv[1]
14 except IndexError:
15 raise RuntimeError('Please specify a filename as an argument to %s' % sys.argv[0])
16
17 in_s = open(filename, 'rb')
18 try:
19 # 读取数据
20 while True:
21 try:
22 o = pickle.load(in_s)
23 except EOFError:
24 break
25 else:
26 print 'READ: %s (%s)' % (o.name, o.name_backwards)
27 finally:
28 in_s.close()
运行这个脚本,可以看到:
~$ python pcs-201-4.py test.dat READ: pickle (elkcip) READ: cPickle (elkciPc) READ: last (tsal)