Pyro4: десериализация класса protobuf - PullRequest
0 голосов
/ 14 января 2019

Я совершенно новичок в 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#changing-the-way-your-custom-classes-are-de-serialized)) я понимаю, что «по умолчанию пользовательские классы сериализуются в dict. Они не десериализуются обратно в экземпляры вашего пользовательского класса».

Я ищу инструкцию или пример, описывающий, как я могу превратить этот сериализованный словарь обратно в мой класс, включая экземпляр сообщения protobuf, который содержит класс.

Кажется, что это должна быть обычная и тривиальная операция, и все же я не могу найти хороший пример, чтобы показать мне, и документация не предоставляет явной помощи, которую я вижу.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Это была действительно сериализация из protobuf, которую я видел. Как только эта конфузия была отсортирована, я обнаружил, что сериализованные результаты были в юникоде. Чтобы я мог получить protobuf для десериализации результатов, мне нужно было закодировать его как чистый ascii (используя <result>.encode('utf-8')). Я не уверен, почему он возвращает юникод, который потом не развернется и не примет. Однако у меня есть рабочее решение.

0 голосов
/ 14 января 2019

По умолчанию 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 о том, как их объекты сериализуются (возможно, вам придется искать, как они травятся). Нижняя линия; это не то, что Пиро (или змея) контролирует.

...