目录

0. 概要

1. 一个简单的例子

2. Module Interface

2.1 pickle.dump(obj, file, protocol = None, *, fix_imports = True)

2.2 pickle.load(file, *, fix_imports = True, encoding = “ASCII”, errors = “strict”)

2.3 pickle.dumps(obj, protocol = None, *, fix_imports = True)

2.4 pickle.loads(bytes_object, *, fix_imports = True, encoding = “ASCII”, errors = “strict”)

3. Pros and Cons of using Pickle Module


0. 概要

The pickle module is used for implementing binary protocols for serializing and de-serializing a Python object structure.

Python pickle模块是对二进制协议的一种实现,用于对于python中的对象结构进行(正向的)序列化(serialization)和(反向的)解序列化(de-serialization)处理。序列化(serialization)将结构化的python对象(如list, dict等)转化为字节流(byte stream),通常也称为pickling,flattening,或者marshalling. 解序列化处理即将由pickling处理生成的字节流反向变换回原来的python对象,也称为unpickling.

为什么需要序列化处理呢? 一言以蔽之,方便数据在不同的系统等之间进行传输、以及以文件或者数据库的方式进行存储。

本文是关于pickle模块的入门级使用方法介绍。

1. 一个简单的例子

要所使用pickling功能,首先当然是要导入pickle模块。

以下例子将一个列表mylist的内容进行序列化处理后,存储到文件datafile.txt中。pickle.dump()函数直接完成了序列化处理以及写入文件的处理。由于转换成了字节序列,所以只能以二进制的格式存入文件,所以open()命令的选项为'wb',其中b表示binary。

import pickle
mylist = ['a', 'b', 'c', 'd']
with open('datafile.txt', 'wb') as fh:
   pickle.dump(mylist, fh)

 运行正常的话,会生成一个名为datafile.txt的文件,打开看看,是以下这个样子。不出意料的是,因为是二进制格式,所以是无法识别的。

python安装keyboard模块 python安装pickle_serialization

所以,更常见的是不用txt后缀,而是用.pkl或者.pickle等后缀,让人一看就知道这是pickle格式。

接下来看看能不能从datafile.txt中恢复出刚才的数据。

pickled_dat = open ("datafile.txt", "rb")
unpickled = pickle.load(pickled_dat)
print(unpickled)

 输出如下,恢复出了原列表数据。


['a', 'b', 'c', 'd']


再看一个对python dict进行序列化和解序列化处理的例子。

staffDict = {1:"Lee",2:"Yao",3:"Zhang",4:"Wang",5:"Liu"}
pickled = open("staffDict.pkl","wb")
pickle.dump(staffDict, pickled)
pickled.close()

pickled = open("staffDict.pkl", 'rb')
recoveredStaffDict = pickle.load(pickled)
print(recoveredStaffDict)


Output: {1: 'Lee', 2: 'Yao', 3: 'Zhang', 4: 'Wang', 5: 'Liu'}


 符合预期。

以上例子用到了pickle.load()和pickle.dump()两个函数的最基本使用方法,也是pickle模块的最基本有用方法。

2. Module Interface

pickle模块包括以下几个函数和常数定义:

(1) dump(): Serialize an object hierarchy and write into a data file

(2) load(): Reverse processing of dump(). Read pickled data stream from data file and de-serialize.

(3) dumps() – This function is called to serialize an object hierarchy into a data stream instead write it into data file.

(4) loads() – This function is called to de-serialize a data stream.

(5) pickle.HIGHEST_PROTOCOL: 整数值,指定最高支持的协议版本号,被dump()和dumps()使用.

(6) pickle.DEFAULT_PROTOCOL: 当未指定protocol参数时,缺省使用的协议代号

2.1 pickle.dump(obj, file, protocol = None, *, fix_imports = True)

这个函数等价于Pickler(file, protocol).dump(obj),函数用于将python对象结果进行序列化处理后写入指定的文件。

可选参数protocol用于指定协议代号,所支持的协议代号从0 to HIGHEST_PROTOCOL(pickle常数).未指定的话,则实用DEFAULT_PROTOCOL,如果指定值为负数的话,则选用HIGHEST_PROTOCOL.

如果参数fix_imports为True且protocol小于等于3, pickle模块将会把新的python3的名字映射到旧的python2的模块名,这样的话,序列化后的数据就可以用python2读取了。python2的消失是注定的虽然还需要一些时间,所以对于初阶用户来说,不太会再碰到python2的东西了,所以不太需要关注这些事情。

以下为pickle.dump()的一个更复杂一些的实用示例。

# pickle.dump()
import pickle
import io

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'))

# Write to the stream
pickled = open("dump.pkl", 'wb')
for o in data:
    print ('WRITING: %s (%s)' % (o.name, o.name_backwards))
pickle.dump(data,pickled)


WRITING: pickle (elkcip) WRITING: cPickle (elkciPc) WRITING: last (tsal)


2.2 pickle.load(file, *, fix_imports = True, encoding = “ASCII”, errors = “strict”)

该函数等价于Unpickler(file).load(),用于从文件中读取序列化后的数据并进行de-serialize恢复出原python对象层次结构.

Example :

# Python program to illustrate
# pickle.load()

# Set up a read-able stream
in_s = io.StringIO(out_s.getvalue())

pickled_dat = open("dump.pkl", 'rb')

unpickled = pickle.load(pickled_dat)

#print(unpickled)

for o in unpickled:
    print ('READ: %s (%s)' % (o.name, o.name_backwards))


READ: pickle (elkcip) READ: cPickle (elkciPc) READ: last (tsal)


2.3 pickle.dumps(obj, protocol = None, *, fix_imports = True)

这个函数与dump()的区别在于它将序列化后的数据存储在一个字节流对象(byte-stream object)中。这里的's'指的是stream.

所以它不需要指定文件名。它返回的就是所生成的字节流对象的handle。

Example :

#Pickle.dumps()
import pickle

data = [ { 'a':'A', 'b':2, 'c':3.0 } ]
data_string = pickle.dumps(data)
print ('PICKLE:', data_string )


PICKLE: b'\x80\x04\x95#\x00\x00\x00\x00\x00\x00\x00]\x94}\x94(\x8c\x01a\x94\x8c\x01A\x94\x8c\x01b\x94K\x02\x8c\x01c\x94G@\x08\x00\x00\x00\x00\x00\x00ua.'


2.4 pickle.loads(bytes_object, *, fix_imports = True, encoding = “ASCII”, errors = “strict”)

它与dumps()构成一对。直接从pickle序列化后的字节流对象恢复出原始的结构层次。

注意,它多了两个参数,一个是encoding,一个是errors.

Example :

# pickle.loads()
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))


BEFORE: [{'a': 'A', 'b': 2, 'c': 3.0}] AFTER: [{'a': 'A', 'b': 2, 'c': 3.0}] SAME?: False EQUAL?: True


3. Pros and Cons of using Pickle Module

pickle模块还提供一些Exceptions以及一些导出的类,属于比较进阶的要素,本文暂时就不介绍了。

Pros:

用于存储复杂的数据结构非常方便,使用简单,代码简单。

序列化的数据是二进制数据,不可读,所以也相当于提供一些最初阶的安全措施。

Cons:

python pickle序列化后的数据没有跨语言通用性,其它编程语言无法识别pickle序列化后的数据.

pickle本身没有安全防护能力,不会进行识别是否恶意数据以及给出警告。当你拿到一个pickle数据时,如果不是很确定其来源和安全性,不建议随便进行序列化处理。否则的话可能会招致安全威胁。