Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping over Protocol Buffers attributes in Python

I would like help with recursively looping over all attributes/sub objects contained in a protocol buffers message, assuming that we do not know the names of them, or how many there are.

As an example, take the following .proto file from the tutorial on the google website:

  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;
}

and to use it...:

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

Given Person, How do I then access both the name of the attribute and its value for each element: person.id, person.name, person.email, person.phone.number, person.phone.type?

I have tried the following, however it doesn't seem to recurs into person.phone.number or 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

I have tried using obj.DESCRIPTOR.fields_by_name.keys to access the sub elements, but these are the string representations of the sub objects, not the objects themselves.

obj.name gives me the attribute of the name, but im not sure how to actually get the value of that attribute, eg obj.name may give me 'name', but how do i get 'john doe' out of it?

like image 992
Toby Avatar asked Mar 19 '15 15:03

Toby


People also ask

What is protocol buffer in Python?

Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once … The ProtoBuf interface describes the structure of the data to be sent.

How do protocol buffers work?

Protocol buffers are a combination of the definition language (created in . proto files), the code that the proto compiler generates to interface with data, language-specific runtime libraries, and the serialization format for data that is written to a file (or sent across a network connection).

How do I read a proto file in Python?

import sys import myprotocol_pb2 as proto import varint # (this is the varint.py file) data = open("filename. bin", "rb"). read() # read file as string decoder = varint. decodeVarint32 # get a varint32 decoder # others are available in varint.py next_pos, pos = 0, 0 while pos < len(data): msg = proto.


1 Answers

I'm not super familiar with protobufs, so there may well be an easier way or api for this kind of thing. However, below shows an example of how you could iterate/introspect and objects fields and print them out. Hopefully enough to get you going in the right direction at least...

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)

which outputs

tutorial.Person.name: John Doe
tutorial.Person.id: 1234
tutorial.Person.email: [email protected]
tutorial.Person.PhoneNumber.number: 1234567890
tutorial.Person.PhoneNumber.type: HOME
like image 142
Jacob Burbach Avatar answered Oct 19 '22 23:10

Jacob Burbach