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

5 投票
2 回答
11499 浏览
提问于 2025-04-15 16:45

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打开文件时就知道该读取多少数据。

2 个回答

4

Python中的字符串可以包含任何字符,也就是说,它们可以直接存储“二进制”数据。你不需要把字符串转换成“二进制”。

4

我对Python不是很精通,但你可以直接把file.read()操作得到的结果放进message.ParseFromString(...)里,不需要再创建什么新的字符串类型或者其他东西。

撰写回答