Python的

我想为属于我的扩展库的对象实施酸洗支持。 有一个启动时初始化的Service类的全局实例。 所有这些对象都是作为一些Service方法调用的结果而产生的,并且实质上属于它们。 Service知道如何将它们序列化为二进制缓冲区以及反序列化缓冲区如何返回到对象中。

似乎Pythons __ reduce__应该服务于我的目的 - 实施酸洗支持。 我开始实现一个,并意识到unpickler存在一个问题(第一个元素od预期会由__ reduce__返回)。 这个unpickle函数需要一个Service的实例,以便能够将输入缓冲区转换为Object。 这里有一些伪代码来说明这个问题:

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不喜欢它:它说它是实例方法,不能被腌制。 显然,pickler正在尝试将例程存储到输出中,并希望Service实例和函数名一起使用,但这并不是我想要发生的事情。 我不希望(并且实际上不能:服务不可选)将服务与所有对象一起存储。 我希望在调用pickle.load之前创建服务实例,并在取出过程中以某种方式使用该实例。

在这里,我来了copy_reg模块。 它再次出现,因为它应该解决我的问题。 这个模块允许动态注册每种类型的pickler和unpickler例程,并且这些应该稍后用于这种类型的对象。 所以我将这个注册添加到服务构建中:

class Service(object):
  ...
  def __init__(self):
      ...
      import copy_reg
      copy_reg( mymodule.Object, self.pickleObject, self.unpickleObject )

self.unpickleObject现在是一个绑定的方法,将服务作为第一个参数,将缓冲区作为第二个参数。 self.pickleObject也是绑定的方法,将服务和对象腌制。 copy_reg要求pickleObject例程应该跟随reducer语义并返回与之前类似的元组。 这里又出现了问题:我应该返回什么作为第一个元组?

class Service(object):
  ...
  def pickleObject(self,obj):
      ...
      return self.unpickleObject, (self.serialize(obj),)

在这种形式下,泡菜再次抱怨说它不能腌制实例方法。 我试过无 - 它也不喜欢它。 我放了一些虚拟功能。 这是有效的 - 意味着序列化过程很好,但在取消打开过程中,它会调用这个虚函数而不是unpickler,我在Service构造函数中注册了mymodule.Object类型。

所以现在我处于亏损状态。 对不起,很长的解释:我不知道如何在几行中提出这个问题。 我可以总结一下我的问题:

  • 为什么copy_reg语义要求我从pickleObject中返回unpickler例程,如果我希望独立注册一个例程?
  • 有没有任何理由喜欢copy_reg.constructor接口注册unpickler例程?
  • 如何让腌菜使用我注册的取代器,而不是一个在流内?
  • 我应该返回作为pickleObject结果值的元组中的第一个元素? 有没有“正确”的价值?
  • 我是否正确地处理了这件事? 有不同/更简单的解决方案吗?
  • 感谢您的时间。

    Gennadiy


    首先, copy_reg模块在这里不太可能帮到你:它主要是将__reduce__类似的特性添加到没有该方法的类中,而不是提供任何特殊的功能(例如,如果你想从一些库本身不支持它)。

    __reduce__返回的可调用__reduce__需要在需要取消对象的环境中定位,因此实例方法并不合适。 正如Pickle文档中提到的:

    在unpickling环境中,此对象必须是一个类,一个可调用的注册为“安全构造函数”(请参见下文),或者它必须具有带真值的属性__safe_for_unpickling__

    所以如果你定义了一个函数(不是方法),如下所示:

    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函数,以便在__reduce__将对象链接到新环境的全局Service对象。

    链接地址: http://www.djcxy.com/p/11123.html

    上一篇: Python's

    下一篇: c on iOS?