如何获取协议缓冲区中的所有字段名?

35 投票
4 回答
49293 浏览
提问于 2025-04-18 12:32

我想把一个proto里的所有字段名都放到一个列表里。有没有什么办法可以做到这一点?我查了文档,似乎没有相关的内容。

4 个回答

1

我在使用Python 3.9的时候遇到了一些问题,之前的一些解决方案不再有效了。所以我找到了一种新的方法,这个方法是通过消息对象的公共接口来实现的,而不是使用DESCRIPTOR属性。

fields = [desc.name for desc, val in message.ListFields()]

不过要注意,这个方法只会获取那些已经设置过的字段。

相关文档在这里:https://googleapis.dev/python/protobuf/latest/google/protobuf/message.html#google.protobuf.message.Message.ListFields

1

你可以很简单地获取一个字段列表,方法如下:

message_fields = [field for field in message.DESCRIPTOR.fields_by_name]
14

这个回答对我没用。我调用 message.DESCRIPTOR.fields.keys() 的时候,出现了 AttributeError: 'list' object has no attribute 'keys' 的错误。

我不太明白为什么会这样。可能和消息是怎么定义或编译的有关。

我的解决办法是把每个字段对象放到一个列表里,然后获取每个字段的 name 属性。这样我就得到了一个包含所有字段名称的字符串列表。

res = [f.name for f in message.DESCRIPTOR.fields]

需要注意的是,这样做并不能递归地获取这些字段内部的字段名称。

55

每个proto类都有一个叫做 DESCRIPTOR类变量,这个变量可以用来查看对应protobuf消息的字段。

想了解更多,可以看看 DescriptorFieldDescriptor 这两个类的文档。

下面是一个简单的例子,展示如何把 message 中所有字段的 FieldDescriptor 放到一个列表里:

res = message.DESCRIPTOR.fields

如果你想获取字段的名字,"正好和它们在.proto文件中出现的一样":

res = [field.name for field in message.DESCRIPTOR.fields]

或者(来自评论):

res = message.DESCRIPTOR.fields_by_name.keys()

如果你想获取字段的全名,"包括它们所在的范围":

res = [field.full_name for field in message.DESCRIPTOR.fields]

撰写回答