2015-05-09 14 views
11

In generale, ho una definizione protobuf che utilizzava una parola chiave Python "from". Funziona in Java/C#/C++, ma quando arriva a Python, non posso assegnargli alcun valore.viene utilizzata in protobuf in Python

Ecco il dettaglio del mio problema.

Ho una definizione protobuf come di seguito:

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

Dal momento che il campo "da" è una parola chiave in Python, dopo aver generato il codice Python, non ho potuto compilare il codice, come di seguito:

foo = Foo() 
foo.from = 1234 

Poi, ho cercato di usare setattr() per impostare l'attributo:

setattr(foo, 'from', 1234) 

che mi dà un'eccezione Protobuf:

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

non ho potuto cambiare la definizione in questo momento perché è stato ampiamente utilizzato nel sistema. Qualsiasi aiuto sarebbe apprezzato se riesco a trovare un modo per usare l'attributo "from" in Python.

riportano di seguito le protobuf codice generato:

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

Non ho mai usato buffer di protocollo prima, ma un idioma comune in Python è di apporre un sottolineare a una parola riservata se si desidera utilizzarlo come identificatore. Forse l'implementazione Python fa la stessa cosa? 'foo = Foo(); foo.from_ = 1234'. – chepner

+0

Interessante domanda. Potresti per favore postare il codice Python risultante generato da protobuf? O da un esempio di lavoro minimo, se non puoi pubblicare l'originale. – Unapiedra

+0

@chepner grazie! Ho provato anche questo. ma sembra che non funzioni. Riporterà l'errore che da_ non è definito. – kerneljoy

risposta

4

Dopo paio di tentativi, ho trovato il setattr() e getattr() può risolvere questo. Perché nel mio codice di produzione, il 'da' si riferisce ad un'altra definizione di protobuff. Quindi la soluzione è la seguente:

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

Grazie di cuore, bel lavoro! Era curioso quale fosse la soluzione. –

0

È strano realizzare "HasField" ma non associare "GetField". Per favore, considera un'altra implementazione:

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 

Puoi usarlo come metodo di utilità o fare mixin se sai come farlo.

0

Se "da" era una variabile primitiva (non composta). l'attributo set funzionerà (puoi vedere nel messaggio di errore: "AttributeError: Assignment not to field composito") - ma se Foo è incluso in un altro oggetto dovrai usare "MergeFrom" per inserire Foo da inserire nell'oggetto incluso.

esempio:

pb:

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

il seguente codice dovrebbe funzionare:

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