如何在python3中获取protobuf的RepeatedCompositeContainer或RepeatedScalarContainer包含的类型?

Fra*_*nka 7 python serialization backend protocol-buffers proto

我正在编写一个用于序列化和发送protobuf3消息的 Python 应用程序。我想制作某种交互式用户界面,允许选择消息并动态分配它。我有一大堆这样的消息,因此我不想get为每条消息创建一个函数,而是创建一个可以处理所有消息的函数。

对于get所有消息字段,我可以简单地获取消息的所有属性并选择其字段,这很容易。然后,为了知道属性是什么类型,我使用type(getattr(my_message, current_field)). 现在问题来了。假设这些是我的消息:

message myMess1 {
    //some fields
}

message myMess2 {
    string some_string = 1
    repeated myMess1 myMess1Field = 2
}
Run Code Online (Sandbox Code Playgroud)

现在,分配 some_string 字段就没有问题了。

type(getattr(myMess2Instance, someStringFieldName))return string,所以我知道用字符串来填充它。

但是重复的 myMess1 字段该怎么办呢? type(getattr(MyMess2Instance, myMess1FieldName))实际上返回google.protobuf.pyext._message.RepeatedCompositeContainer,它没有说明其中包含什么类型。我怎么才能得到它?

Azi*_*lto 5

我遇到了类似的 Protobuf 解析问题,这就是我所做的“希望有帮助”:

假设我们有这样的响应消息:

>>> msg
path {
}
path {
  value: "Arts & Entertainment"
}
path {
  value: "Comics & Animation"
}
Run Code Online (Sandbox Code Playgroud)

将其转换为字典:

>>> from google.protobuf.json_format import MessageToDict
>>> d = MessageToDict(msg)
{'path': ['', 'Arts & Entertainment', 'Comics & Animation']}
Run Code Online (Sandbox Code Playgroud)

将字典值列表作为字符串连接:

>>> " ".join(d["path"]).strip()
'Arts & Entertainment Comics & Animation'
Run Code Online (Sandbox Code Playgroud)


Mor*_*hit 5

这确实让我困惑了一段时间,因为似乎没有生成任何文档。关键是要看到它的RepeatedCompositeContainer行为像一个列表。您可以迭代内容,在示例中将具有myMess1生成的类型。例如:

for myMess1Element in myMess2Instance.myMess1FieldName:
    print(f"{myMess1Element.some_field=}")
    print(f"{myMess1Element.other_field=}")
Run Code Online (Sandbox Code Playgroud)

如果您以某种方式提前知道该消息的重复次数,则可以为特定消息建立索引。例如:

print(f"{myMess2Instance.myMess1FieldName[0]}")
Run Code Online (Sandbox Code Playgroud)

不过,建议检查长度,因为消息可以重复任意次数(包括零次)。