

Python标准库: pickle模块——对象序列化和反序列化
source link: https://sineatos.github.io/tools/programme-language/python/stdlib/pickle/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Python标准库: pickle模块——对象序列化和反序列化
在Python2中有pickle模块和cPickle模块,而在Python3中只有pickle模块,其中py2中的pickle模块由python实现,cPickle模块由C实现,后者效率更高,但是后者定义的类型不能被集成(其实大多数时候我们不需要从这些类型中继承)。到了py3,pickle模块已经被cPickle模块代替了。
当然,上述的两个模块其实实现的功能是一样的,所以可以交错使用,同时这两个模块在处理自引用问题时会更加”聪明”,它不会无限的递归序列化自引用对象,对于同一个对象的多次引用,它只会序列化一次。如:
import marshal, pickle
list = [1]
list.append(list)
byt1 = marshal.dumps(list)
#出错, 无限制的递归序列化
byt2 = pickle.dumps(list)
#No problem
pickle的序列化规则
- Python规范(Python-specific)提供了pickle的序列化规则。这就不必担心不同版本的Python之间序列化兼容性问题。
- 默认情况下,pickle的序列化是基于文本的,我们可以直接用文本编辑器查看序列化的文本。我们也可以序列成二进制格式的数据,这样的结果体积会更小。
- 更详细的内容,可以参考Python手册pickle模块。
pickle常用方法和类
pickle.dump(obj, file[, protocol=0])
序列化对象,并将结果数据流写入到文件对象中。参数protocol
是序列化模式,默认值为0,表示以文本的形式序列化。protocol
的值还可以是1或2,表示以二进制的形式序列化。
pickle.load(file)
反序列化对象。将文件中的数据解析为一个Python对象。下面通过一个简单的例子来演示上面两个方法的使用:
import pickle, StringIO
class Person(object):
'''自定义类型。'''
def __init__(self, name, address):
self.name = name
self.address = address
def display(self):
print('name:', self.name, 'address:', self.address)
jj = Person("JGood", "中国 杭州")
jj.display()
file = StringIO.StringIO()
pickle.dump(jj, file, 0) #序列化
#print file.getvalue() #打印序列化后的结果
#del Person #反序列的时候,必须能找到对应类的定义。否则反序列化操作失败。
file.seek(0)
jj1 = pickle.load(file) #反序列化
jj1.display()
file.close()
注意:在反序列化的时候,必须能找到对应类的定义,否则反序列化将失败。在上面的例子中,如果取消#del Person
的注释,在运行时将抛AttributeError
异常,提示当前模块找不到Person
的定义。也就是说,反序列化的时候需要提前导入类的定义。
pickle.dumps(obj[, protocol])
pickle.loads(string)
我们也可以直接获取序列化后的数据流,或者直接从数据流反序列化。方法dumps
与loads
就完成这样的功能。dumps
返回序列化后的数据流,loads
返回的序列化生成的对象。
python模块中还定义了两个类,分别用来序列化、反序列化对象。
class pickle.Pickler(file[, protocal]):
该类用于序列化对象。参数file是一个类文件对象(file-like object),用于保存序列化结果。可选参数表示序列化模式。它定义了两个方法:
dump(obj):
将对象序列化,并保存到类文件对象中。参数obj是要序列化的对象。
clear_memo()
清空pickler的“备忘”。使用Pickler实例在序列化对象的时候,它会“记住”已经被序列化的对象引用,所以对同一对象多次调用dump(obj),pickler不会“傻傻”的去多次序列化。下面是一个简单的例子:
#coding=gbk
import pickle, StringIO
class Person(object):
'''自定义类型。'''
def __init__(self, name, address):
self.name = name
self.address = address
def display(self):
print('name:', self.name, 'address:', self.address)
fle = StringIO.StringIO()
pick = pickle.Pickler(fle)
person = Person("JGood", "Hangzhou China")
pick.dump(person)
val1 = fle.getvalue()
print(len(val1))
pick.clear_memo() #注释此句,再看看运行结果
pick.dump(person) #对同一引用对象再次进行序列化
val2 = fle.getvalue()
print(len(val2))
#---- 结果 ----
#148
#296
#
#将这行代码注释掉:pick.clear_memo()
#结果为:
#148
#152
class pickle.Unpickler(file):
该类用于反序列化对象。参数file是一个类文件(file-like object)对象,Unpickler从该参数中获取数据进行反序列化。
load():
反序列化对象。该方法会根据已经序列化的数据流,自动选择合适的反序列化模式。
#.... 接上个例子中的代码
fle.seek(0)
unpick = pickle.Unpickler(fle)
print(unpick.load())
上面介绍了pickle模块的基本使用,但和marshal一样,并不是所有的类型都可以通过pickle序列化的。例如对于一个嵌套的类型,使用pickle序列化就失败。例如:
class A(object):
class B(object):
def __init__(self, name):
self.name = name
def __init__(self):
print 'init A'
b = A.B("my name")
print(b)
c = pickle.dumps(b, 0) #失败哦
print(pickle.loads(c))
关于pickle支持的序列化类型,可以参考Python手册。
</article
Recommend
-
12
Python Pickle反序列化带来的安全问题 GaRY
-
27
在对数据进行序列化和反序列化是常见的数据操作,Python提供了两个模块方便开发者实现数据的序列化操作,即 json 模块和 pickle 模块。这两个模块主要区别如下: json 是一个文本序列化格式,而 pickle 是一个二进制序列化格...
-
17
Serializing Objects With the Python pickle Module As a developer, you may sometimes need to send complex object hierarchies over a network or save the internal state of your objects to a disk or database for later use. To accomplish...
-
9
飞哥讲代码24:从Python Pickle漏洞说起 时间: 2021-03-13 | 分类:
-
10
【Python】pickle&json序列化 2017年10月06日 Author: Guofei 文章归类: Python语法 ,文章编号: 1211 版权声明:本文作者是郭飞。转载随意...
-
10
V2EX › Python Python 的 pickle 加载大于内存上限的内容时会分段载入吗?应该怎么处理大文件读取?
-
11
pickle — Python object serialization¶ Source code:
-
11
python pickle Posted by chunyang on May 18, 2022...
-
6
常用的标准库 序列化模块 import pickle 序列化和反序列化 把不能直接存储的数据变得可存储,这个过程叫做序列化。把文件中的数据拿出来,回复称原来的数据类型,这个过程叫做反序列化。 在...
-
5
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 大家好我是费老师,相信不少读...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK