序列化和反序列化_序列化与反序列化:pickle

本文约2180字,建议阅读时间12~15分钟

关键字:python,序列化,反序列化,字节编码,pickle

pickle模块主要用于将python对象与二进制序列之间的转换,是python所特有的,pickle模块是不安全的,只有当把字节序列转换为python对象时才是可信的,当操作不可信的数据时,建议使用json格式。pickle模块会追踪已经被序列化对象的位置,所以随后对相同对象的引用将不再被序列化。

目前存在6种不同的pickle协议,通常越高的python版本可以使用更高级的协议。

版本

特征

version 0

人类可读,与较早版本的python兼容

version 1

旧式二进制形式,与较早版本的python兼容

version 2

python2.3引入,提供更有效的pickle类型

version 3

python3.0新增,支持bytes对象,不能被python2反pickle

version 4

python3.4新增,支持超大对象及更多类型的对象

version 5

python3.8新增,支持带外数据,加速带内数据

 将python对象序列化,可使用dumps函数,相反可使用loads函数。通常创建Pickler和Unpickler对象可以更多地对序列化与反序列化进行控制。

1、相关常数

(1)pickle.HIGHEST_PROTOCOL

最高pickle协议版本号(整数),可以作为dumps、loads函数以及Pickler构造函数的protocol参数的值。

(2)pickle.DEFUALT_PROTOCOL

pickle的默认协议版本号(整数),当前默认值为4,可能小于HIGHEST_PROTOCOL.

2、相关函数

(1)将python对象写入pickle文件

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

#obj为python对象,file为pickle文件

#等同于Pickler(file,protocol).dump(obj)

import pickle as pk

data='This is the corpus of family name.'

with open('data.pickle','wb') as f:

    pk.dump(data,f,pk.HIGHEST_PROTOCOL)

#在本地生成data.pickle文件

#注:二进制写为’wb’

(2)将python对象转换为bytes对象

pickle.dumps(obj,protocol=None,*)

pk.dumps('abc')

#返回b'\x80\x04\x95\x07\x00\x00\x00\x00\x00\x00\x00\x8c\x03abc\x94.'

(3)读取pickle文件

pickle.load(file,*)

#file为pickle文件

#其他主要参数encoding默认为’ASCII’,errors默认为’strict’

#等同于Unpickler(file).load()

with open('data.pickle','rb') as f:

    data=pk.load(f)

print(data)

返回:

'This is the corpus of family name.'

(4)将类bytes对象转换为python对象

pickle.loads(obj_b,*)

#obj_b为类bytes对象

pk.loads(pk.dumps('abc'))

#返回’abc’

3、相关异常

pickle.PickleError

#继承自Exception

pickle.PicklingError

#继承自PickleError

pickle.UnpicklingError

#继承自PickleError

4、相关类

(1)Pickler

创建Pickler对象(写入器)

pickler=pickle.Pickler(file,protocol=None,*)

数据写入

pickler.dump(obj)

#obj为python对象

持久化

pickler.persistent_id(obj)

默认情况下什么都不做,如果返回None,obj将被正常序列化,如果返回其他值,pickler对象将把其作为obj的持久化 ID。持久化ID是Unpickler.persistent_load()定义的。

分发表

pickler.dispatch_table

分发表是可以通过copyreg.pickle()函数声明的压缩注册表,它是键为类、值为压缩函数的映射。一个压缩函数只有与类相关的单参数并且应该遵循同样的接口作为__reduce__()方法。

压缩重载

reducer_override(self,obj)

在pickler子类中可定义的特殊压缩器,在dispatch_table中该方法生成的压缩器比其他压缩器具有优先级,python3.8新增。

快速转换模式

pickler.fast

不推荐使用,当被设置真实值时能够快速转换。

(2)Unpickler

创建Unpickler对象(读取器)

unpickler=pickle.Unpickler(file,*)

#还可以设置主要参数encoding=’ASCII’,errors=’strict’

数据读取

unpickler.load()

持久化

unpickler.persistent_load(pid)

默认抛出UnpicklingError,如果定义了,将返回被持久化ID特殊化的对象,如果遇到非法的持久化ID,将抛出UnpicklingError。

导入模块的名称

unpickler.find_class(module,name)

module和name都为字符串,也可以用于发现模块中的函数。

(3)PickleBuffer

创建PickleBuffer对象

picklebuffer=PickleBuffer(buffer)

一个代表可pickle数据缓冲器的装饰器,buffer必须是一个buffer-providing对象,比如类字节对象或者n维数组。该对象只能采用协议5或者更高版本时才可序列化,它是python3.8新增的。

picklebuffer.raw()

返回buffer的内存查看对象memoryview

picklebuffer.release()

释放潜在的缓冲

5、可pickle和反pickle的对象

(1)None、True、False;

(2)整数、浮点数、复数;

(3)字符串、字节,字节组;

(4)元组、列表、集合、字典中仅包含可pickle的对象;

(5)定义在模块顶层的函数(如def定义的而非lambda定义的);

(6)定义在模块顶层的内建函数;

(7)定义在模块顶层的类;

(8)那些拥有__dict__或者调用__getstate__()的结果可pickle的类的实例;

当pickle函数或类时,只有函数或类的名称可被pickle。

6、pickle类的实例

默认情况下,pickle将通过内在机制回溯类和实例的属性,当一个类的实例不能被pickle时,它的__init__()方法将不被唤起,默认的行为是首先创建一个非初始化的实例,然后恢复已经保存的属性。当类提供了如下一种或多种特殊方法时将改变这种默认的行为:

(1)object.__getnewargs_ex__()

在协议2及以上的版本中,在反pickle时类通过执行该方法时能够控制传递给__new__()方法的值,该方法返回元组对(args,kwargs)。当类中的__new__()方法只需要关键字参数时应该执行该方法。

(2)object.__getnewargs__()

该方法与object.__getnewargs_ex__()具有相同的目的,只是该方法仅支持位置参数,且返回args的元组。如果object.__getnewargs_ex__()被定义了,则该方法将不能被调用。

(3)object.__getstate__()

如果类定义了该方法,调用时返回的对象被pickle成实例目录,而不是实例字典的目录。

(4)object.__setstate__(state)

如果定义了该方法,在反pickle状态时将被调用,此时没有必要将状态对象设成字典,否则在pickle状态时必须将字典的元素分配到新的实例字典中。

上述方法在pickle时并不会直接使用,事实上,这些方法是执行__reduce__()特殊方法的复制协议的一部分。在类中直接执行__reduce__()方法是易于出错的,因此应该使用诸如上述方法等高级接口。

(5)object.__reduce__()

该方法不带参数,通常返回元组,也可以是字符串。

(6)object.__reduce_ex__(protocol)

该方法需要一个整型参数,即协议版本号。

7、类型、函数和其他对象的自定义压缩

有时,分发表可能并不足够灵活,例如基于其他规则的自定义pickle而不是基于对象的类型,或者自定义函数和类的pickle,可以通过创建Pickler的子类和执行reducer_override()方法来实现,这种方法将返回一个随机的元组。如果dispatch_table和reducer_override()被同时定义,那么reducer_override()将拥有更高优先级。

(完)

ca2505dc434bbb57f6823e840e760ecd.png

欢迎关注【lambda派】!

相关阅读:

迭代器函数模块itertools

数理统计模块statistics

派生枚举类:IntEnum、IntFlag、Flag

数组二分插入:bisect

堆队列:heapq

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值