如何解决协议缓冲区 ParseFromString 函数未在 Python 作家读者
我正在测试协议缓冲区并尝试读取 csv 文件,对其进行序列化并将输出写入二进制文件,然后使用 ParseFromString 读取二进制文件。我能够序列化和写入二进制文件,但是在读取它时会给出一个索引越界异常,或者在其他情况下它只输出二进制文件的最后一行,它会跳过它之前的所有内容。
我的消息很简单,它有两个字段,时间和度量使用。
Syntax="proto3";
message excelData {
string time=1;
string meterusage=2;
}
import metric_pb2
import sys
from csv import reader
excel_data=metric_pb2.excelData()
with open('out.bin','wb') as f:
with open('data.csv','r') as read_obj:
csv_reader = reader(read_obj)
header = next(csv_reader)
if header != None:
for row in csv_reader:
excel_data.time=row[0]
excel_data.meterusage=row[1]
f.write(excel_data.SerializetoString())
f.close()
read_obj.close()
麻烦的部分如下:
方法 1:这只返回二进制文件的最后一行。它会跳过它之前的所有内容。
excel_data=metric_pb2.excelData()
with open('out.bin','rb') as f:
content=f.read()
excel_data.ParseFromString(content)
print(excel_data.time)
print(excel_data.meterusage)
方法 2:如果我像上面的 csv 文件一样读取序列化的二进制文件,它会给我一个索引越界错误。我的倾向是,二进制文件可能是字节数据并且不包含字符串数据类型,因此会出现此错误?
使用 message.ParseFromString() 读取这个二进制文件的正确方法是什么,因为通过循环读取它不起作用,也不完整地读取它?我创建的二进制文件的快照如下:
解决方法
你成功了吗?
这里有一个 hacky 解决方案(根据 streaming multiple messages 的 Protobuf 技术)将(变量!)消息长度写为每条记录之前的字节。
作家
import metric_pb2
import sys
from csv import reader
excel_data = metric_pb2.excelData()
with open('out.bin','wb') as f:
with open('data.csv','r') as read_obj:
csv_reader = reader(read_obj)
header = next(csv_reader)
if header != None:
for row in csv_reader:
excel_data.time = row[0]
excel_data.meterusage = row[1]
bytes = excel_data.SerializeToString()
# Write the message's integer length as bytes
f.write(len(bytes).to_bytes(1,sys.byteorder))
# Write the message itself as bytes
f.write(bytes)
f.close()
read_obj.close()
产生:
00000000: 1c 0a13 3230 3231 2d30 312d 3031 2030 303a 3030 3a30 3012 0535 342e 3635 ...2021-01-01 00:00:00..54.65
00000010: 1c 0a13 3230 3231 2d30 312d 3031 2030 303a 3030 3a30 3012 0535 352e 3138 ...2021-01-01 00:00:00..55.18
00000030: 1b 0a13 3230 3231 2d30 312d 3031 2030 303a 3030 3a30 3012 0435 352e 38 ...2021-01-01 00:00:00..55.8
注意 1c
== 28(因为 54.65
和 55.18
)和 1b
== 27(因为 55.8
)
读者
import metric_pb2
import sys
excel_data = metric_pb2.excelData()
with open('out.bin','rb') as f:
while True:
# Read the message's length as bytes and convert it to an integer
len = int.from_bytes(f.read(1),sys.byteorder)
# Read that number of bytes as the message bytes
bytes = f.read(len)
if not bytes:
break
excel_data.ParseFromString(bytes)
print("[{time}] {meterusage}".format(
time=excel_data.time,meterusage=excel_data.meterusage))
产生:
[2021-01-01 00:00:00] 54.65
[2021-01-01 00:00:00] 55.18
[2021-01-01 00:00:00] 55.8
[2021-01-01 00:00:00] 56.0
[2021-01-01 00:00:00] 63.52
[2021-01-01 00:00:00] 78.1
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。