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')). Я не уверен, почему он возвращает юникод, который потом не развернется и не примет. Однако у меня есть рабочее решение.

Другие вопросы по тегам