【问题标题】:Trouble saving repeated protobuf object to file (Python)无法将重复的 protobuf 对象保存到文件(Python)
【发布时间】:2020-07-24 19:02:22
【问题描述】:

我是 protobuf 的新手,所以我不知道如何正确地提出问题。

无论如何,我正在使用这个Model Config proto 文件。我使用来自Protocol Buffer page 的这个命令protoc -I=. --python_out=. ./model_server_config.proto 将它转换为python。现在我有一些可以导入和处理的 python 文件。我的目标是创建一个文件(用于运行具有多个模型的 TensorFlow 模型服务器),该文件应如下所示:

model_config_list: {
 config: {
    name: "name1",
    base_path: "path1",
    model_platform: "tensorflow"
  },
  config: {
    name: "name2",
    base_path: "path2",
    model_platform: "tensorflow"
  },
  config: {
    name: "name3",
    base_path: "path3",
    model_platform: "tensorflow"
  },
}

现在使用编译的python包,我制作了一个protobuf对象,当我打印出来时看起来像这样:

model_config_list {
  config {
    name: "name1"
    base_path: "path1"
    model_platform: "tensorflow"
  }
  config {
    name: "name2"
    base_path: "path2"
    model_platform: "tensorflow"
  }
  config {
    name: "name3"
    base_path: "path3"
    model_platform: "tensorflow"
  }
}

但是在使用objectname.SerializeToString() 序列化对象时,我得到一个奇怪的输出:

b'\n\x94\x01\n \n\x04name1\x12\x0cpath1"\ntensorflow\n7\n\x08name2\x12\x1fpath2"\ntensorflow\n7\n\x08name3\x12\x1fpath3"\ntensorflow'

我尝试使用 python 的 protobuf 将其转换为 Json,如下所示:

from google.protobuf.json_format import MessageToJson
MessageToJson(objectname)

这给了我这样的结果:

{
  "modelConfigList": {
    "config": [
      {
        "name": "name1",
        "basePath": "path1",
        "modelPlatform": "tensorflow"
      },
      {
        "name": "name2",
        "basePath": "path2",
        "modelPlatform": "tensorflow"
      },
      {
        "name": "name3",
        "basePath": "path3",
        "modelPlatform": "tensorflow"
      }
    ]
  }
}

所有对象都在一个列表中,每个对象都是字符串,这对于 TensorFlow 模型服务器配置是不可接受的。

关于如何正确将其写入文件的任何想法?还是我错误地创建了整个对象?欢迎任何帮助,提前致谢。

【问题讨论】:

标签: python tensorflow protocol-buffers proto protobuf-python


【解决方案1】:

我不知道什么系统会读取你的文件,所以我不能说你应该如何将它写入文件。这实际上取决于模型服务器希望如何读取它。

也就是说,我认为您创建消息的方式或您展示的任何序列化方法没有任何问题。

  • print 方法显示了一个“文本格式”的原型,有利于调试,有时用于存储配置文件。它不是很紧凑(文件中存在字段名称),并且没有二进制表示的所有向后和向前兼容的特性。它实际上在功能上与您所说的“应该看起来像”相同:冒号和逗号实际上是可选的。
  • SerializeToString() 方法使用二进制 serialization format。这可以说是构建协议缓冲区的目的。它是一种紧凑的表示形式,并提供向后和向前兼容性,但它的可读性不是很好。
  • 顾名思义,json_format 模块提供消息的 JSON 表示。如果您与之交互的系统需要 JSON,那就太好了,但这并不常见。

附录:google.protobuf.text_format 模块没有使用print(),而是具有更适合以编程方式使用文本格式的实用程序。要写入文件,您可以使用:

from google.protobuf import text_format
(...)
with open(file_path, 'w') as output:
  text_format.PrintMessage(my_message, output)

【讨论】:

  • 感谢您的回复。我对这个概念很陌生,所以我不确定我对这个回复的理解程度。我的目标是创建一个像 tensorflow.org/tfx/serving/… 这样的配置文件。但是如果我将它序列化并写入文件,它就不起作用并抛出这个错误Error parsing text-format tensorflow.serving.ModelServerConfig: 2:1: Interpreting non ascii codepoint 148.
  • 引用该页面:“提供的模型服务器配置文件必须是 ASCII ModelServerConfig 协议缓冲区。请参阅以下内容以了解 ASCII 协议缓冲区的外观。”似乎他们期望上面的文本格式(您从print 获得的格式)。它(不幸的是)有时被称为“ASCII 格式”,尽管这是用词不当(它实际上使用 utf-8)。
  • 那么将该信息保存到文件的最佳方式是什么?
  • 我会使用text_format 模块而不是打印,这与print() 相同,但有更多的控制以编程方式使用。 PrintMessage() 在这里看起来特别有用。
猜你喜欢
  • 2014-10-08
  • 1970-01-01
  • 2013-07-10
  • 2020-02-24
  • 2015-05-31
  • 2016-02-21
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多