目的:Python对象序列化
可用性:pickle至少1.4版本,cPickle 1.5版本以上
pickle
模块实现了一种算法,将任意一个Python对象转化成一系列字节(byets)。此过程也调用了serializing
对象。表明对象的字节流以后能够被传输或存储,再重构后建立一个拥有相同特征(the same characteristics)的新的对象。
cPickle
使用C而不是Python,实现了相同的算法。这比Python实现要快好几倍,可是它不容许用户从Pickle派生子类。若是子类对你的使用来讲可有可无,那么cPickle是个更好的选择。
警告:本文档直接说明,pickle不提供安全保证。若是你在多线程通讯(inter-process communication)或者数据存储或存储数据中使用pickle,必定要当心。请勿信任你不能肯定为安全的数据。
导入
如日常同样,尝试导入cPickle,给它赋予一个别名“pickle”。若是由于某些缘由导入失败,退而求其次到Python的原生(native)实现pickle模块。若是cPickle可用,能给你提供一个更快速的执行,不然只能是轻便的执行(the portable implementation)。
try: import cPickle as pickle except: import pickle
编码和解码
第一个例子将一种数据结构编码成一个字符串,而后把该字符串打印至控制台。使用一种包含全部原生类型(native types)的数据结构。任何类型的实例均可被腌渍(pickled,译者注:模块名称pickle的中文含义为腌菜),在稍后的例子中会演示。使用pickle.dumps()
来建立一个表示该对象值的字符串。
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字符组成。也可使用更高效的二进制格式(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)而构造一个具备相同值得新对象。
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)
如你所见,这个新构造的对象与原对象相同,但并不是同一对象。这不足为奇。
$ 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还提供一对用在类文件流(file-like streams)的转化函数。能够往一个流中写对个对象,而后从流中把它们读取出来,此过程不须要预先写入的对象有几个、它们多大。
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模拟一个文件 out_s = StringIO() # 写入该流 for o in data: print 'WRITING: %s (%s)' % (o.name, o.name_backwards) pickle.dump(o, out_s) out_s.flush() # 创建一个可读流 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)模拟流,因此在创建可读流的时候咱们玩了一把。一个简单数据库的格式化也可使用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),从一个管道(pipe)读取做业指令(job instruction)而后将结果写入另外一个管道。管理工做者池(worker pool)和将做业送入、接受响应(response)的核心代码可被重用,由于做业和响应并不属于某个特定类中。若是你使用管道或者套接字(sockets),在经过连至另外一端(end)的链接倾倒(dumps)全部对象、推送数据以后,别忘了冲洗(flush)。若是你想写本身的工做者池管理器,请看multiprocessing
。
原文:pickle and cPickle – Python object serialization - Python Module of the Week 的前半部分