用Python protobuf如何读取C++二进制protobuf数据?

5

Google protobuf 的 Python 版本仅提供以下内容:

SerializeAsString()

相比之下,C++版本可以同时提供以下两个功能:

SerializeToArray(...)
SerializeAsString()

我们正在以二进制格式编写我们的C++文件,并希望保持这种方式。话虽如此,是否有一种方法可以将二进制数据读入Python并解析它,就像它是一个字符串一样?
binary = get_binary_data()
binary_size = get_binary_size()

string = None
for i in range(len(binary_size)):
   string += i

message = new MyMessage()
message.ParseFromString(string)

更新:

以下是一个新的例子和一个问题:

message_length = 512

file = open('foobars.bin', 'rb')

eof = False
while not eof:

    data = file.read(message_length)
    eof = not data

    if not eof:
        foo_bar = FooBar()
        foo_bar.ParseFromString(data)

当我们到达foo_bar.ParseFromString(data)这一行时,我会收到以下错误:

Exception Type: DecodeError
Exception Value: Too many bytes when decoding varint.

更新2:

事实证明,二进制数据的填充使protobuf出现了问题;太多的字节被发送进去了,正如消息所示(在这种情况下,它指的是填充)。

这个填充来自于使用C++ protobuf函数 SerializeToArray在固定长度缓冲区上。为了消除这个问题,我使用了以下临时代码:

message_length = 512

file = open('foobars.bin', 'rb')

eof = False
while not eof:

    data = file.read(message_length)
    eof = not data

    string = ''
    for i in range(0, len(data)):
        byte = data[i]
        if byte != '\xcc': # yuck!
            string += data[i]

    if not eof:
        foo_bar = FooBar()
        foo_bar.ParseFromString(string)

我认为这里存在设计缺陷。我将重新实现我的C++代码,以便将可变长度数组写入二进制文件。根据protobuf文档的建议,我将在每个消息前加上它的二进制大小,这样当我使用Python打开文件时就知道要读取多少数据。


我不确定你的循环要做什么,但是这样做会引发TypeError。你把None赋值给了string变量,然后试图将一系列int添加到它上面。在Python中,字符串是一系列字节,因此任何二进制数据都应该安全地存储在字符串中。你能否更清楚地解释一下SerializeAsString对你的数据做了什么错误的事情? - jcdyer
2个回答

4

虽然我不是Python专家,但你可以将file.read()操作的结果直接传递给message.ParseFromString(...),而不需要构建新的字符串类型或其他内容。


4

Python字符串可以包含任何字符,即它们能够直接存储“二进制”数据。因此,无需将字符串转换为“二进制”。


3
Python 3 已经不再如此。 - sorin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接