- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想为属于我的扩展库的对象实现 pickle 支持。有一个在启动时初始化的类服务的全局实例。所有这些对象都是作为某些服务方法调用的结果而产生的,并且本质上属于它。服务知道如何将它们序列化为二进制缓冲区以及如何将缓冲区反序列化回对象。
看来 Python 的 __reduce__ 应该符合我的目的 - 实现 pickling 支持。我开始实现一个并意识到 unpickler 存在问题(元组的第一个元素预计由 __ reduce__ 返回)。此 unpickle 函数需要服务实例才能将输入缓冲区转换为对象。下面是一些伪代码来说明这个问题:
class Service(object):
...
def pickleObject(self,obj):
# do serialization here and return buffer
...
def unpickleObject(self,buffer):
# do deserialization here and return new Object
...
class Object(object):
...
def __reduce__(self):
return self.service().unpickleObject, (self.service().pickleObject(self),)
注意元组中的第一个元素。 Python pickler 不喜欢它:它说它是 instancemethod 并且不能被 pickle。显然,pickler 试图将例程存储到输出中,并且需要服务实例和函数名称,但这不是我想要发生的。我不想(而且真的不能:服务不可挑选)将服务与所有对象一起存储。我希望在调用 pickle.load 之前创建服务实例,并以某种方式在 unpickling 期间使用该实例。
这里是我通过 copy_reg 模块来的。它再次出现,因为它应该可以解决我的问题。该模块允许动态注册每种类型的 pickler 和 unpickler 例程,这些例程应该稍后用于这种类型的对象。所以我将此注册添加到服务构造中:
class Service(object):
...
def __init__(self):
...
import copy_reg
copy_reg( mymodule.Object, self.pickleObject, self.unpickleObject )
self.unpickleObject 现在是一个绑定(bind)方法,将服务作为第一个参数,缓冲区作为第二个参数。 self.pickleObject 也是将服务和对象 pickle 的绑定(bind)方法。 copy_reg 要求 pickleObject 例程应遵循 reducer 语义并返回与以前类似的元组。问题又来了:元组的第一个元素应该返回什么??
class Service(object):
...
def pickleObject(self,obj):
...
return self.unpickleObject, (self.serialize(obj),)
在这种形式中,pickle 再次提示它无法 pickle instancemethod。我试过无 - 它也不喜欢它。我在那里放了一些虚拟函数。这有效 - 这意味着序列化阶段进行得很好,但在 unpickling 期间它调用这个虚拟函数而不是 unpickler 我在服务构造函数中注册了 mymodule.Object 类型。
所以现在我很茫然。很抱歉解释很长:我不知道如何用几行来问这个问题。我可以这样总结我的问题:
最佳答案
首先,copy_reg
模块在这里不太可能帮到你:它主要是一种向没有该功能的类添加类似 __reduce__
功能的方法方法而不是提供任何特殊能力(例如,如果你想从一些本身不支持它的库中挑选对象)。
__reduce__
返回的可调用对象需要位于对象要被解封的环境中,因此实例方法并不合适。如 Pickle documentation 中所述:
In the unpickling environment this object must be either a class, a callable registered as a “safe constructor” (see below), or it must have an attribute
__safe_for_unpickling__
with a true value.
所以如果你定义一个函数(不是方法)如下:
def _unpickle_service_object(buffer):
# Grab the global service object, however that is accomplished
service = get_global_service_object()
return service.unpickleObject(buffer)
_unpickle_service_object.__safe_for_unpickling__ = True
您现在可以在 __reduce__
方法的返回值中使用此 _unpickle_service_object
函数,以便您的对象链接到新环境的全局 Service
未 pickle 时的对象。
关于Python 的 __reduce__/copy_reg 语义和有状态的 unpickler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12065657/
我一直在用 Python 制作一个简单的数据库,我开始在 Windows PC 上处理它,现在已经适应了使用装有 Linux 的笔记本电脑。 我制作并一直在使用的脚本在我的 Windows 电脑上运行
我有一个包含这一行的 git 子模块 import copy_reg 它适用于 Python 2。但是,Python3 中没有名为copy_reg 的模块。Python3 模块名称是 copyreg。
我想为属于我的扩展库的对象实现 pickle 支持。有一个在启动时初始化的类服务的全局实例。所有这些对象都是作为某些服务方法调用的结果而产生的,并且本质上属于它。服务知道如何将它们序列化为二进制缓冲区
我在处理多处理时遇到了 pickling 错误: from multiprocessing import Pool def test_func(x): return x**2 clas
我正在尝试解开存储为 MySQL 数据库中 blob 的对象。我已经手动生成了 pickle 对象并将其存储在数据库中,但是当我尝试取消 pickle 对象时,我得到了以下相当神秘的异常: Impor
我是一名优秀的程序员,十分优秀!