pickle和cPickle——python对象序列化

来源:互联网 发布:为什么要反乌托邦 知乎 编辑:程序博客网 时间:2024/05/16 02:58

pickle和cPickle——python对象序列化

pickle模块引入了一个基础的但是强大的python对象序列化和反序列化的方法。(pickling and unpickling)

picking 是这样一个过程——把python对象转化为二进制流的形式,unpickling是这个的逆过程。


注意:pickle模块是不安全的,Hacker可能利用pickle模块进行恶意代码注入。对于picking过程而言并不需要担心,因为它产生的都是string,但是对于unpickling过程,unpicke一个不受信赖的string不一定是安全的,因为unpickle很可能产生无法预料的对象。所以要注意你unpickle的string的来源。

与pickle模块相近的一个模块是cPickle,正如其名它是使用c语言写的,相比之下它的速度大约是pickle模块的1000倍,然而cPickle相比pickle不支持Pickler()和Unpickler()的子类,因为在cPickle模块中只有函数并没有类的存在。cPickle模块和pickle模块在某些情况下可以互用,比如对于一个数据流(使用dump存储在文件中的数据),我们既可以使用cPickle模块的load方法也可以使用pickle模块的load方法进行读取。

<span style="font-size:14px;">>>> import cPickle>>> import pickle>>> class Foo:name = 'wang'>>> f = open('N:\\wang.txt','w')>>> cPickle.dump(Foo,f)>>> f.close()>>> f = open('N:\\wang.txt','r')>>> print pickle.load(f)__main__.Foo>>> f.close()>>> f = open('N:\\wang.txt','r')>>> print cPickle.load(f)__main__.Foo>>> f.close()</span>

Python有一个更原始的模块来支持序列化——marshal ,通常情况下pickle模块的性能总是比marshal模块要好,marshal的存在主要是为了支持Python的.pyc文件。

关于pyc文件不做详细介绍,这里只需知道Python的原始代码在运行前都会被先编译成字节码,并把编译的结果保存到一个一个的PyCodeObject中,pyc 文件即是把PyCodeObject从内存中以marshal格式保存到文件后的结果。


数据流格式:

pickle生成的数据流格式是Python独有的,它的优点是在被外部标准引用时是无限制的,但是对于非Python的应用无法解析pickle产生的数据流。

默认情况下,pickle生成的数据流格式使用可打印的ASCII码,对于程序员来说具有易读性,我们只需要打开存储的txt文件就能容易的理解生成的数据流,看一下上面代码中wang.txt中的内容:

c__main__
Foo
p1

很容易理解。目前在pickling中有三种不同的协议:

protocol 0 :原始的ASCII协议,向后兼容

protocol 1:老的二进制格式,同样向后兼容

protocol 2:Python2.3引入,对于新式类(new-style classes)提供了更有效的pickling


Example:

<span style="font-size:14px;">import pickledata1 = {'a': [1, 2.0, 3, 4+6j],         'b': ('string', u'Unicode string'),         'c': None}selfref_list = [1, 2, 3]selfref_list.append(selfref_list)output = open('data.pkl', 'wb')# Pickle dictionary using protocol 0.pickle.dump(data1, output)# Pickle the list using the highest protocol available.pickle.dump(selfref_list, output, -1)output.close()</span>

<span style="font-size:14px;">import pprint, picklepkl_file = open('data.pkl', 'rb')data1 = pickle.load(pkl_file)pprint.pprint(data1)data2 = pickle.load(pkl_file)pprint.pprint(data2)pkl_file.close()</span>

可以被pickle的数据类型:

  • NoneTrue, and False
  • integers, long integers, floating point numbers, complex numbers
  • normal and Unicode strings
  • tuples, lists, sets, and dictionaries containing only picklable objects
  • functions defined at the top level of a module
  • built-in functions defined at the top level of a module
  • classes that are defined at the top level of a module
  • instances of such classes whose __dict__ or the result of calling __getstate__() is picklable (see section The pickle protocol for details).




0 0
原创粉丝点击