将序列化的 protobuf 输出转换为 python 字典

问题描述 投票:0回答:2

给出一个字符串格式的序列化protobuf(协议缓冲区)输出。我想将它转换为Python字典。

假设这是序列化的 protobuf,以 python 字符串形式给出:

person {
  info {
    name: John
    age: 20
    website: "https://mywebsite.com"
    eligible: True
  }
}

我想将上面的Python字符串转换为Python字典

data
,给出为:

data = {
  "person": {
    "info": {
      "name": "John",
      "age": 20,
      "website": "https://mywebsite.com",
      "eligible": True,
    }
  }
}

我可以编写一个Python脚本来进行转换,如下:

  • 在不以大括号结尾的每一行添加逗号。
  • 在左大括号前添加一个额外的冒号。
  • 用引号将每个单独的键和值对括起来。
  • 最后使用
    json.loads()
    方法将其转换为Python字典。

我想知道是否可以使用协议缓冲区中已有的更简单或标准方法来实现这种转换。那么,除了使用我上面提到的步骤手动编写脚本之外,是否有更好或标准的方法可用于将序列化的 protobuf 输出转换为 python 字典?

python json dictionary protocol-buffers
2个回答
2
投票

您可以使用

proto
Message
类。

In [6]: import proto

In [7]: curr
Out[7]:
campaign {
  resource_name: "customers/1234/campaigns/5678"
  id: 9876
  name: "testing 1, 2, 3"
  advertising_channel_type: SEARCH
}
landing_page_view {
  resource_name: "customers/1234/landingPageViews/1234567890"
  unexpanded_final_url: "https://www.example.com/"
}

In [8]: proto.Message.to_dict(
   ...:     curr,
   ...:     use_integers_for_enums=False,
   ...:     including_default_value_fields=False,
   ...:     preserving_proto_field_name=True
   ...: )
Out[8]:
{'campaign': {'resource_name': 'customers/1234/campaigns/5678',
  'advertising_channel_type': 'SEARCH',
  'name': 'testing 1, 2, 3',
  'id': '9876'},
 'landing_page_view': {'resource_name': 'customers/1234/landingPageViews/1234567890',
  'unexpanded_final_url': 'https://www.example.com/'}}

请注意,在

to_dict
中,所有 kwargs 默认为
True

如果您只想立即序列化消息而不必使用

to_json
,还有一个
json.dumps
方法。

还值得注意的一个警告是

proto
包的 最近内存泄漏。该线程表示已发布修复程序,但我在较大数据集上使用它时的经验表明并非如此。仅仅因为某些东西在本地工作,并不意味着您部署它的容器可以处理相同的负载。


0
投票

您可以使用google包MessageToDict函数将proto3消息转换为python dict。

您必须根据要求设置很少的参数。 use_integers_for_enums:如果为 true,则打印整数而不是枚举名称。 Descriptor_pool:用于解析类型的描述符池。如果没有使用 默认。 serving_proto_field_name:如果为 True,则使用原始 proto 字段 .proto 文件中定义的名称。如果为 False,则转换字段 名称改为小驼峰命名法。 include_default_value_fields:如果为 True,则单数原始字段, 重复字段和映射字段将始终被序列化。如果 False,仅序列化非空字段。单一消息字段 and oneof 字段不受此选项影响。

从 google.protobuf.json_format 导入 MessageToDict 导入 test_pb2 作为 test_pb2

python_dict = MessageToDict(消息,serving_proto_field_name=True,include_default_value_fields=True,descriptor_pool=test_pb2.test_output)["output_list"]

我的 proto3 文件有 test_output 作为模块的输出

© www.soinside.com 2019 - 2024. All rights reserved.