Подтвердить что ты не робот

Зарезервированное ключевое слово используется в protobuf в Python

В общем, у меня есть определение protobuf, в котором используется ключевое слово Python "from" . Он работает в Java/С#/С++, но когда приходит на Python, я не могу присвоить ему значение.

Вот деталь моей проблемы.

У меня есть определение protobuf, как показано ниже:

message Foo
{
    required int64 from = 10
    ...
}

Поскольку поле "from" является ключевым словом в Python, после того, как я сгенерировал код python, я не смог скомпилировать код, как показано ниже:

foo = Foo()
foo.from = 1234

Затем я попытался использовать setattr() для установки атрибута:

setattr(foo, 'from', 1234)

Это дает мне исключение Protobuf:

AttributeError: Assignment not allowed to composite field "from" in protocol message object.

Я не мог изменить определение в данный момент, потому что он широко использовался в системе. Любая помощь будет оценена, если я могу обходным путем использовать атрибут "from" в Python.

Ниже приведен код, созданный ProtoBuf:

import sys


_FOO = _descriptor.Descriptor(
  name='Foo',
  full_name='com.kerneljoy.Foo',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='from', full_name='com.kerneljoy.Foo.from', index=0,
      number=10, type=3, cpp_type=2, label=2,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=28,
  serialized_end=47,
)

DESCRIPTOR.message_types_by_name['Foo'] = _FOO

Foo = _reflection.GeneratedProtocolMessageType('Foo', (_message.Message,), dict(
  DESCRIPTOR = _FOO,
  __module__ = 'Foo_pb2'
  # @@protoc_insertion_point(class_scope:com.kerneljoy.Foo)
  ))
_sym_db.RegisterMessage(Foo)
4b9b3361

Ответ 1

После попыток пары я обнаружил, что setattr() и getattr() могут обойти это. Потому что в моем производственном коде "от" относится к другому определению протобафа. Итак, решение здесь выглядит следующим образом:

foo = Foo()
object = getattr(foo, 'from')
object.bar = 'value'
object.bar2 = 'value2'

Ответ 2

Странно осознавать "HasField", но не соединяет "GetField". Пожалуйста, рассмотрите еще одну реализацию:

def msg_GetField(msg, name, default_value=None, raise_on_not_exist=True):
    result = default_value
    #
    exist = False
    items = msg.ListFields()
    for desc, value in items:
        if name == desc.name:
            result = value
            exist = True
    #
    if raise_on_not_exist:
        if not exist:
            raise ValueError('No property')
    #
    return result

Вы можете использовать его как метод утилиты или сделать mixin, если знаете, как это сделать.

Ответ 3

Если "from" - это примитивная переменная (не составная). атрибут set будет работать (вы можете увидеть в ошибке msg: "AttributeError: Assignment не разрешено составное поле" ), но если Foo включен в другой объект, вам нужно будет использовать "MergeFrom", для вставки Foo для вставки его в объект включения.

Пример:

pb:

message Foo
{
   required int64 from = 1
} 
message Bar
{
  required Foo foo = 1
}

должен работать следующий код:

foo=Foo()
bar=Bar()
setattr(foo, 'from', 1204)
bar.MergeFrom(foo)