2015-03-19 17 views
6

Vorrei ottenere aiuto con il ricorsivo loop su tutti gli attributi/sotto oggetti contenuti in un messaggio di buffer di protocollo, supponendo che non conosciamo i loro nomi, o quanti ce ne sono.Looping degli attributi di Protocol Buffers in Python

A titolo di esempio, prendete il seguente file Proto dal tutorial sul sito web di Google:

message Person { 
    required string name = 1; 
    required int32 id = 2; 
    optional string email = 3; 

    enum PhoneType { 
    MOBILE = 0; 
    HOME = 1; 
    WORK = 2; 
    } 

    message PhoneNumber { 
    required string number = 1; 
    optional PhoneType type = 2 [default = HOME]; 
    } 

    repeated PhoneNumber phone = 4; 
} 

e di utilizzarlo ...:

person = tutorial.Person() 
person.id = 1234 
person.name = "John Doe" 
person.email = "[email protected]" 
phone = person.phone.add() 
phone.number = "555-4321" 
phone.type = tutorial.Person.HOME 

Dato Person, come faccio quindi accedere sia al nome dell'attributo che al suo valore per ciascun elemento: person.id, person.name, person.email, person.phone.number, person.phone.type?

Ho provato quanto segue, tuttavia non sembra ricorrere in person.phone.number o person.phone.type.

object_of_interest = Person 

while(hasattr(object_of_interest, "_fields")): 
    for obj in object_of_interest._fields: 
    # Do_something_with_object(obj) # eg print obj.name 
    object_of_interest = obj 

Ho provato con obj.DESCRIPTOR.fields_by_name.keys accedere agli elementi secondari, ma queste sono le rappresentazioni di stringa degli oggetti secondari, non gli oggetti stessi.

obj.name mi dà l'attributo del nome, ma non sono sicuro di come ottenere effettivamente il valore di tale attributo, ad esempio obj.name potrebbe darmi 'nome', ma come faccio a ottenere 'john doe' fuori di esso?

risposta

16

Non ho molta familiarità con i protobuf, quindi potrebbe esserci un modo più semplice o api per questo genere di cose. Tuttavia, di seguito viene mostrato un esempio di come è possibile iterare/introspezionare e campi degli oggetti e stamparli. Speriamo che abbastanza per farti andare nella giusta direzione, almeno ...

import addressbook_pb2 as addressbook 

person = addressbook.Person(id=1234, name="John Doe", email="[email protected]") 
person.phone.add(number="1234567890") 


def dump_object(obj): 
    for descriptor in obj.DESCRIPTOR.fields: 
     value = getattr(obj, descriptor.name) 
     if descriptor.type == descriptor.TYPE_MESSAGE: 
      if descriptor.label == descriptor.LABEL_REPEATED: 
       map(dump_object, value) 
      else: 
       dump_object(value) 
     elif descriptor.type == descriptor.TYPE_ENUM: 
      enum_name = descriptor.enum_type.values[value].name 
      print "%s: %s" % (descriptor.full_name, enum_name) 
     else: 
      print "%s: %s" % (descriptor.full_name, value) 

dump_object(person) 

che emette

tutorial.Person.name: John Doe 
tutorial.Person.id: 1234 
tutorial.Person.email: [email protected] 
tutorial.Person.PhoneNumber.number: 1234567890 
tutorial.Person.PhoneNumber.type: HOME 
+1

Cracking, grazie :). –

Problemi correlati