2015-05-09 3 views
11

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

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

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

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

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

foo = Foo() 
foo.from = 1234 

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

setattr(foo, 'from', 1234) 

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

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) 
+1

Я никогда не использовал буфера протокола раньше, но общие идиомы в Python, чтобы приклеивать Подчеркните знак зарезервированного слова, если вы хотите использовать его как идентификатор. Возможно, реализация Python делает то же самое? 'foo = Foo(); foo.from_ = 1234'. – chepner

+0

Интересный вопрос. Не могли бы вы опубликовать полученный код Python, который генерируется protobuf? Или из небольшого рабочего примера, если вы не можете опубликовать оригинал. – Unapiedra

+0

@chepner спасибо! Я тоже это пробовал. но кажется, что это не работает. Он сообщит об ошибке, что from_ не определен. – kerneljoy

ответ

4

После пары попыток я нашел SetAttr() и GetAttr() может обойти это. Потому что в моем производственном коде «от» относится к другому определению протобафа. Таким образом, решение здесь выглядит следующим образом:

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

Круто спасибо, хорошая работа! Любопытно, что это за решение. –

0

Странно понимать «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 

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

0

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

пример:

рь:

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

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

foo=Foo() 
bar=Bar() 
setattr(foo, 'from', 1204) 
bar.MergeFrom(foo) 
Смежные вопросы