pythonprotocol-bufferspyro4

Pyro4: Deserializing protobuf class


I am completely new to Pyro4. I wish to serve a python class which includes an attribute which is an instance of a protobuf object compiled to a python class.

import sys
import os
import Pyro4
import MPB_pb2 as mpb  # My Protobuf class

@Pyro4.expose
@Pyro4.behavior(instance_mode="single")
class MyWrappedProtobuf(object):
    def __init__(self):
        self.setup_MyProtobuf()

    def setup_MyProtobuf(self):
        self.__MyProtobuf = mpb.MyProtobufMessage()

    @property
    def MyProtobuf(self):
        return self.__MyProtobuf

After setting the server running, I create a proxy of the served object, and query the MyProtobuf property:

u = Pyro4.Proxy('PYRONAME:{}'.format(<server name>)).MyProtobuf

What I get back is a serialized object:

>>>u
{'serialized': '\n$\n\x05world\x12\x1b\t\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\x00'}

I understand from the documents (https://pythonhosted.org/Pyro4/clientcode.html#changing-the-way-your-custom-classes-are-de-serialized) that "By default, custom classes are serialized into a dict. They are not deserialized back into instances of your custom class."

I am looking for instruction, or an example describing how I can go about turning this serialized dictionary back into my class, including the protobuf message instance that class contains.

It seems like this must be a common, and trivial operation, and yet I can't find a good example to show me, and the documentation is not providing explicit help that I can see.

Thank you!


Solution

  • By default, Pyro uses the Serpent serializer, which in turn uses python's primitive types to serialize stuff into. Usually this will be a dictionary. If it's a class it doesn't readily recognize or the class doesn't have a "suitable" serialization method defined, it will fall back to a special dictionary form such as this:

    {
        "__class__":   "pakcage.Classname"
        "property1":   "value1",
        ...
    }
    

    You're not seeing this in your serialized form. Which means it wasn't Pyro (or Serpent, rather) that serialized it for you. What happened (I think) is that a Protobuf object defines a __getstate__() method that returns the serialized form of the protobuf object that you're seeing. The reverse of this is __setstate__(...) (these methods are 'borrowed' from Python's built in pickle serializer mechanism). I don't have experience with protobufs but my guess is that a simple:

    u = proxy.MyProtoBuf
    message = mpb.MyProtobufMessage()   # create empty protobuf object (??)
    message.__setstate__(u)
    

    will do the trick. I advise you to look into protobuf's documentation about how their objects are serialized (you may have to search for how they are pickled). Bottom line; this is not something Pyro (or serpent) has control over.