简体   繁体   English

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

[英]How to get type contained by protobuf's RepeatedCompositeContainer or RepeatedScalarContainer in python3?

I'm writing a Python app for serializing and sending protobuf3 messages.我正在编写一个用于序列化和发送protobuf3消息的 Python 应用程序。 I'd like to make some sort of interactive UI that allows to choose a message and assign it on the fly.我想制作某种交互式用户界面,允许选择一条消息并即时分配它。 I've got a pretty big set of those messages, thus I don't want to make a get function for every message, but make one that will work with all of them.我有一大堆这些消息,因此我不想为每条消息都创建一个get函数,而是创建一个可以处理所有消息的函数。

To get all message fields, I can simply get all the message's attributes and choose those that are its fields, which is easy.get所有消息字段,我可以简单地获取所有消息的属性并选择那些作为其字段的属性,这很容易。 Then, to know what type is the attribute, I use type(getattr(my_message, current_field)) .然后,要知道属性是什么类型,我使用type(getattr(my_message, current_field)) And now there is the problem.现在问题来了。 Suppose those are my messages:假设这些是我的消息:

message myMess1 {
    //some fields
}

message myMess2 {
    string some_string = 1
    repeated myMess1 myMess1Field = 2
}

Now, there is no problem with assigning some_string field.现在,分配 some_string 字段没有问题。

type(getattr(myMess2Instance, someStringFieldName)) returns string , so I know to feed it with string. type(getattr(myMess2Instance, someStringFieldName))返回string ,所以我知道用字符串提供它。

But what to do with the repeated myMess1 field?但是如何处理重复的 myMess1 字段呢? type(getattr(MyMess2Instance, myMess1FieldName)) actually returns google.protobuf.pyext._message.RepeatedCompositeContainer , which says nothing about what type is contained in it. type(getattr(MyMess2Instance, myMess1FieldName))实际上返回google.protobuf.pyext._message.RepeatedCompositeContainer ,它没有说明其中包含的类型。 How can I get it?我怎么才能得到它?

I had a similar Protobuf parsing issue, here is what I do "hope it helps":我有一个类似的 Protobuf 解析问题,这是我所做的“希望它有帮助”:

Say we have this response message:假设我们有这个响应消息:

>>> msg
path {
}
path {
  value: "Arts & Entertainment"
}
path {
  value: "Comics & Animation"
}

Convert it to dictionary:将其转换为字典:

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

Join the dictionary list of values as a string:将值的字典列表作为字符串加入:

>>> " ".join(d["path"]).strip()
'Arts & Entertainment Comics & Animation'

This really perplexed me for a while since no documentation seems to be generated.这确实让我困惑了一段时间,因为似乎没有生成任何文档。 The key is to see that RepeatedCompositeContainer behaves like a list.关键是要看到RepeatedCompositeContainer行为就像一个列表。 You can iterate on the contents, which in the example would have the myMess1 generated type.您可以对内容进行迭代,在示例myMess1生成myMess1类型。 Eg:例如:

for myMess1Element in myMess2Instance.myMess1FieldName:
    print(f"{myMess1Element.some_field=}")
    print(f"{myMess1Element.other_field=}")

If you somehow knew the number of repeats of that message ahead of time, you could index a particular one.如果您以某种方式提前知道该消息的重复次数,则可以索引特定的消息。 Eg:例如:

print(f"{myMess2Instance.myMess1FieldName[0]}")

It would be advisable to check the length though, since the message could be repeated any number of times (including zero).但是,建议检查长度,因为消息可以重复任意次数(包括零次)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM