目的:Python对象序列化
可用性:pickle最少1.4版本,cPickle 1.5版本以上
pickle
模块实现了1种算法,将任意1个Python对象转化成1系列字节(byets)。此进程也调用了serializing
对象。代表对象的字节流以后可以被传输或存储,再重构后创建1个具有相同特点(the
same characteristics)的新的对象。
cPickle
使用C而不是Python,实现了相同的算法。这比Python实现要快好几倍,但是它不允许用户从Pickle派生子类。如果子类对你的使用来讲无关紧要,那末cPickle是个更好的选择。
正告:本文档直接说明,pickle不提供安全保证。如果你在多线程通讯(inter-process communication)或数据存储或存储数据中使用pickle,1定要谨慎。请勿信任你不能肯定为安全的数据。
如平常1样,尝试导入cPickle,给它赋予1个别名“pickle”。如果由于某些缘由导入失败,退而求其次到Python的原生(native)实现pickle模块。如果cPickle可用,能给你提供1个更快速的履行,否则只能是轻便的履行(the portable implementation)。
try:
import cPickle as pickle
except:
import pickle
第1个例子将1种数据结构编码成1个字符串,然后把该字符串打印至控制台。使用1种包括所有原生类型(native types)的数据结构。任何类型的实例都可被腌渍(pickled,译者注:模块名称pickle的中文含义为腌菜),在稍后的例子中会演示。使用pickle.dumps()
来创建1个表示该对象值的字符串。
try:
import cPickle as pickle
except:
import pickle
import pprint
data = [ { 'a':'A', 'b':2, 'c':3.0 } ]
print 'DATA:',
pprint.pprint(data)
data_string = pickle.dumps(data)
print 'PICKLE:', data_string
pickle默许仅由ASCII字符组成。也能够使用更高效的2进制格式(binary format),只是由于在打印的时候更容易于理解,本页的所有例子都使用ASCII输出。
$ python pickle_string.py
DATA:[{'a': 'A', 'b': 2, 'c': 3.0}]
PICKLE: (lp1
(dp2
S'a'
S'A'
sS'c'
F3
sS'b'
I2
sa.
数据被序列化以后,你可以将它们写入文件、套接字、管道等等中。以后你也能够从文件中读取出来、将它反腌渍(unpickled)而构造1个具有相同值得新对象。
try:
import cPickle as pickle
except:
import pickle
import pprint
data1 = [ { 'a':'A', 'b':2, 'c':3.0 } ]
print 'BEFORE:',
pprint.pprint(data1)
data1_string = pickle.dumps(data1)
data2 = pickle.loads(data1_string)
print 'AFTER:',
pprint.pprint(data2)
print 'SAME?:', (data1 is data2)
print 'EQUAL?:', (data1 == data2)
如你所见,这个新构造的对象与原对象相同,但并不是同1对象。这不足为奇。
$ python pickle_unpickle.py
BEFORE:[{'a': 'A', 'b': 2, 'c': 3.0}]
AFTER:[{'a': 'A', 'b': 2, 'c': 3.0}]
SAME?: False
EQUAL?: True
除dumps()
和loads()
外,pickle还提供1对用在类文件流(file-like
streams)的转化函数。可以往1个流中写对个对象,然后从流中把它们读取出来,此进程不需要预先写入的对象有几个、它们多大。
try:
import cPickle as pickle
except:
import pickle
import pprint
from StringIO import StringIO
class SimpleObject(object):
def __init__(self, name):
self.name = name
l = list(name)
l.reverse()
self.name_backwards = ''.join(l)
return
data = []
data.append(SimpleObject('pickle'))
data.append(SimpleObject('cPickle'))
data.append(SimpleObject('last'))
# 使用StringIO摹拟1个文件
out_s = StringIO()
# 写入该流
for o in data:
print 'WRITING: %s (%s)' % (o.name, o.name_backwards)
pickle.dump(o, out_s)
out_s.flush()
# 建立1个可读流
in_s = StringIO(out_s.getvalue())
# 读数据
while True:
try:
o = pickle.load(in_s)
except EOFError:
break
else:
print 'READ: %s (%s)' % (o.name, o.name_backwards)
这个例子使用SringIO缓存器(buffer)摹拟流,所以在建立可读流的时候我们玩了1把。1个简单数据库的格式化也能够使用pickles来存储对象,只是shelve
与之工作更加简便。
$ python pickle_stream.py
WRITING: pickle (elkcip)
WRITING: cPickle (elkciPc)
WRITING: last (tsal)
READ: pickle (elkcip)
READ: cPickle (elkciPc)
READ: last (tsal)
除存储数据,pickles在进程间通讯(inter-process communication)中也非常称手。例如,使用os.fork()
和os.pipe()
可以创建工作者进程(worker
processes),从1个管道(pipe)读取作业指令(job instruction)然后将结果写入另外一个管道。管理工作者池(worker pool)和将作业送入、接受响应(response)的核心代码可被重用,由于作业和响应其实不属于某个特定类中。如果你使用管道或套接字(sockets),在通过连至另外一端(end)的连接倾倒(dumps)所有对象、推送数据以后,别忘了冲洗(flush)。如果你想写自己的工作者池管理器,请看multiprocessing
。
上一篇 yum使用总结-升级篇
下一篇 JDOM生成、解析XML实例