Pyro4: десериализация класса protobuf
Я совершенно новичок в Pyro4. Я хочу обслуживать класс Python, который включает в себя атрибут, который является экземпляром объекта protobuf, скомпилированного в класс Python.
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
После настройки работы сервера я создаю прокси обслуживаемого объекта и запрашиваю свойство MyProtobuf:
u = Pyro4.Proxy('PYRONAME:{}'.format(<server name>)).MyProtobuf
Я получаю сериализованный объект:
>>>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'}
Из документов я понимаю ( https://pythonhosted.org/Pyro4/clientcode.html), что "по умолчанию пользовательские классы сериализуются в dict Они не десериализованы обратно в экземпляры вашего пользовательского класса."
Я ищу инструкцию или пример, описывающий, как я могу превратить этот сериализованный словарь обратно в мой класс, включая экземпляр сообщения protobuf, который содержится в этом классе.
Кажется, что это должна быть обычная и тривиальная операция, и все же я не могу найти хороший пример, чтобы показать мне, и документация не предоставляет явной помощи, которую я могу видеть.
Спасибо!
2 ответа
По умолчанию Pyro использует сериализатор Serpent, который, в свою очередь, использует примитивные типы python для сериализации. Обычно это будет словарь. Если это класс, который он не может легко распознать, или у класса не определен "подходящий" метод сериализации, он вернется к специальной форме словаря, такой как эта:
{
"__class__": "pakcage.Classname"
"property1": "value1",
...
}
Вы не видите это в своей сериализованной форме. Это означает, что это был не Пиро (точнее, Змей), который сериализировал его для вас. Произошло (я думаю) то, что объект Protobuf определяет метод __getstate__(), который возвращает сериализованную форму объекта protobuf, который вы видите. Обратной стороной этого является __setstate__(...) (эти методы "заимствованы" из встроенного в Python механизма сериализации pickle). У меня нет опыта работы с protobufs, но я думаю, что все просто:
u = proxy.MyProtoBuf
message = mpb.MyProtobufMessage() # create empty protobuf object (??)
message.__setstate__(u)
сделает свое дело. Я советую вам заглянуть в документацию protobuf о том, как их объекты сериализуются (возможно, вам придется искать, как они травятся). Нижняя линия; это не то, что Пиро (или змей) контролирует.
Это была действительно сериализация из protobuf, которую я видел. Как только эта конфузия была отсортирована, я обнаружил, что сериализованные результаты были в юникоде. Чтобы я мог получить protobuf для десериализации результатов, мне нужно было закодировать его как чистый ascii (используя <result>.encode('utf-8')
). Я не уверен, почему он возвращает юникод, который потом не развернется и не примет. Однако у меня есть рабочее решение.