在 Python 中循环 Protocol Buffers 属性
Looping over Protocol Buffers attributes in Python
我希望得到帮助,以递归方式遍历协议缓冲区消息中包含的所有 attributes/sub 对象,假设我们不知道它们的名称或数量。
以google网站教程中的以下.proto文件为例:
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;
}
并使用它...:[=23=]
person = tutorial.Person()
person.id = 1234
person.name = "John Doe"
person.email = "jdoe@example.com"
phone = person.phone.add()
phone.number = "555-4321"
phone.type = tutorial.Person.HOME
给定 Person
,然后如何访问每个元素的属性名称及其值:person.id
、person.name
、person.email
、person.phone.number
, person.phone.type
?
我尝试了以下方法,但它似乎并没有出现在 person.phone.number
或 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
我试过使用 obj.DESCRIPTOR.fields_by_name.keys
访问子元素,但这些是子对象的字符串表示,而不是对象本身。
obj.name 给我名称的属性,但我不确定如何实际获取该属性的值,例如 obj.name 可能会给我 'name',但如何我从中得到 'john doe'?
我对 protobufs 不是很熟悉,所以对于这种事情可能有更简单的方法或 api。但是,下面显示了一个示例,说明如何 iterate/introspect 和对象字段并将它们打印出来。希望至少能让你朝着正确的方向前进......
import addressbook_pb2 as addressbook
person = addressbook.Person(id=1234, name="John Doe", email="foo@example.com")
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)
输出
tutorial.Person.name: John Doe
tutorial.Person.id: 1234
tutorial.Person.email: foo@example.com
tutorial.Person.PhoneNumber.number: 1234567890
tutorial.Person.PhoneNumber.type: HOME
我希望得到帮助,以递归方式遍历协议缓冲区消息中包含的所有 attributes/sub 对象,假设我们不知道它们的名称或数量。
以google网站教程中的以下.proto文件为例:
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;
}
并使用它...:[=23=]
person = tutorial.Person()
person.id = 1234
person.name = "John Doe"
person.email = "jdoe@example.com"
phone = person.phone.add()
phone.number = "555-4321"
phone.type = tutorial.Person.HOME
给定 Person
,然后如何访问每个元素的属性名称及其值:person.id
、person.name
、person.email
、person.phone.number
, person.phone.type
?
我尝试了以下方法,但它似乎并没有出现在 person.phone.number
或 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
我试过使用 obj.DESCRIPTOR.fields_by_name.keys
访问子元素,但这些是子对象的字符串表示,而不是对象本身。
obj.name 给我名称的属性,但我不确定如何实际获取该属性的值,例如 obj.name 可能会给我 'name',但如何我从中得到 'john doe'?
我对 protobufs 不是很熟悉,所以对于这种事情可能有更简单的方法或 api。但是,下面显示了一个示例,说明如何 iterate/introspect 和对象字段并将它们打印出来。希望至少能让你朝着正确的方向前进......
import addressbook_pb2 as addressbook
person = addressbook.Person(id=1234, name="John Doe", email="foo@example.com")
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)
输出
tutorial.Person.name: John Doe
tutorial.Person.id: 1234
tutorial.Person.email: foo@example.com
tutorial.Person.PhoneNumber.number: 1234567890
tutorial.Person.PhoneNumber.type: HOME