наследование сообщения для добавления дополнительного поведения - PullRequest
0 голосов
/ 07 марта 2019

Не знаю, почему это не работает, я хочу создать подкласс сообщения и добавить дополнительное поведение:

import data_pb2 as pb2

class Status(pb2.Status):
    def __init__(self, streamer, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.streamer = streamer

    def __setattr__(self, key, value):
        super().__setattr__(key, value)
        self.streamer.send_update()

Когда кто-то изменяет сообщение pb2.Status, я хочу вызвать send_update. Это бесполезное сообщение об ошибке, которое я получаю:

Traceback (most recent call last):
  File "server.py", line 62, in <module>
    class Status(pb2.Status):
  File "C:\AppData\Local\conda\conda\envs\lib\site-packages\google\protobuf\internal\python_message.py", line 126, in __new__
    descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
KeyError: 'DESCRIPTOR'

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Я нашел решение, которое работает.Когда сообщение обновляется, у меня происходит событие потока и вызывается его метод set.

class Status:
    def __init__(self, *args, **kwargs):
        self.status = pb2.Status(*args, **kwargs)
        self.event = None

    def __setattr__(self, key, value):
        if key == 'status' or key == 'event':
            super().__setattr__(key, value)
        else:
            super().__getattribute__('status').__setattr__(key, value)
            super().__getattribute__('event').set()

    def __getattr__(self, item):
        if item == 'event' or item == 'status':
            return super().__getattribute__(item)
        else:
            return super().__getattribute__('status').__getattribute__(item)


event = threading.Event()
status = Status(version="1",
                )
status_streamer = StatusStreamer(status, event)
status.event = event
status.version = str(int(status.version) + 1) #this triggers set to be called inside setattr, which results in the threads in SatusStreamer to stream the update

Это немного глупо, но поскольку мы не можем подклассифицировать сообщение, это приемлемо.статус - это сообщение, а событие - событие потока, когда эти элементы назначаются и запускаются, они не инициируют устанавливаемое событие.Однако, когда ему назначаются любые другие атрибуты, запускается .set (), которая приводит к обновлению клиентов.

0 голосов
/ 07 марта 2019

Только что обнаружил досадную истину в том, что мы не собираемся расширять классы сообщений:

https://developers.google.com/protocol-buffers/docs/pythontutorial

Буферы протокола и классы буфера OO Design Protocol в основном являются глупыми держателями данных (например,строит в с);они не делают хороших граждан первого класса в объектной модели.Если вы хотите добавить более богатое поведение к сгенерированному классу, лучший способ сделать это - обернуть сгенерированный класс буфера протокола в класс, специфичный для приложения.Обертывание протокольных буферов также является хорошей идеей, если у вас нет контроля над дизайном файла .proto (например, если вы повторно используете один из другого проекта).В этом случае вы можете использовать класс-оболочку для создания интерфейса, более подходящего для уникальной среды вашего приложения: скрытия некоторых данных и методов, предоставления вспомогательных функций и т. Д. Никогда не следует добавлять поведение в сгенерированные классы путем наследованияиз них .Это сломает внутренние механизмы и в любом случае не является хорошей объектно-ориентированной практикой.

...