pickle和cPickle:Python对象的序列化(上)

目的:Python对象序列化
可用性:pickle至少1.4版本,cPickle 1.5版本以上html


pickle模块实现了一种算法,将任意一个Python对象转化成一系列字节(byets)。此过程也调用了serializing对象。表明对象的字节流以后能够被传输或存储,再重构后建立一个拥有相同特征(the same characteristics)的新的对象。python

cPickle使用C而不是Python,实现了相同的算法。这比Python实现要快好几倍,可是它不容许用户从Pickle派生子类。若是子类对你的使用来讲可有可无,那么cPickle是个更好的选择。算法

警告:本文档直接说明,pickle不提供安全保证。若是你在多线程通讯(inter-process communication)或者数据存储或存储数据中使用pickle,必定要当心。请勿信任你不能肯定为安全的数据。数据库

导入

如日常同样,尝试导入cPickle,给它赋予一个别名“pickle”。若是由于某些缘由导入失败,退而求其次到Python的原生(native)实现pickle模块。若是cPickle可用,能给你提供一个更快速的执行,不然只能是轻便的执行(the portable implementation)。缓存

pythontry:
   import cPickle as pickle
except:
   import pickle

编码和解码

第一个例子将一种数据结构编码成一个字符串,而后把该字符串打印至控制台。使用一种包含全部原生类型(native types)的数据结构。任何类型的实例均可被腌渍(pickled,译者注:模块名称pickle的中文含义为腌菜),在稍后的例子中会演示。使用pickle.dumps()来建立一个表示该对象值的字符串。安全

pythontry:
    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$ 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)而构造一个具备相同值得新对象。多线程

pythontry:
    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)

如你所见,这个新构造的对象与原对象相同,但并不是同一对象。这不足为奇。app

python$ 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)的转化函数。能够往一个流中写对个对象,而后从流中把它们读取出来,此过程不须要预先写入的对象有几个、它们多大。socket

pythontry:
    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$ 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 的前半部分

相关文章
相关标签/搜索