在 msgpack 0.6 中获取字节偏移量
Getting byte offsets in msgpack 0.6
在我的场景中,我需要允许随机访问使用 msgpack 序列化的单个项目。 IE。给定一个二进制文件和一个项目索引,我想跳转到文件中的那个位置并反序列化这个项目。
为了获取每个项目的字节偏移量,我使用 mgspack.Unpacker
的 unpack
函数。在 mgspack 0.5 中,unpack
接受一个可选参数 write_bytes
,它是一个在序列化之前在原始数据字符串上调用的挂钩。计算这个字符串的 len
可以得到项目的大小(以字节为单位),这样我就可以累积字节偏移量。
自 msgpack 0.6 以来,write_bytes
参数不再被接受,我没有找到任何替代品给我 raw 输入字符串或消耗的字节数阅读一个项目后。
这是我用来创建索引的函数。函数 returns 将索引作为字节偏移列表。每个条目 index[i]
都包含项目 i
的字节偏移量。关键部分是 unpacker.unpack(write_bytes=hook)
调用,它不再接受任何属性。
def index_from_recording(filename):
# create empty index
index = []
# hook that keeps track of the byte offset of the `msgpack.Unpacker`
hook = ByteOffsetHook()
with open(filename, "rb") as f:
# create the `msgpack.Unpacker`
unpacker = msgpack.Unpacker(f)
try:
while True:
# add current offset to index
index.append(hook.offset)
# unpack (and discard) next item.
# The `hook` keeps track of the read bytes
unpacker.unpack(write_bytes=hook) # <== `write_bytes` not accepted since 0.6
except msgpack.OutOfData:
pass
return index
ByteOffsetHook
定义如下。钩子简单地计算原始输入字符串的 len
并累积它。
class ByteOffsetHook(object):
def __init__(self):
self.offset = 0
def __call__(self, data):
self.offset += len(data)
为了调试,您可以使用此函数生成虚拟录音。
def serialize_dummy_recording(filename):
with open(filename, "wb") as f:
for serialized_sample in [msgpack.packb({'x': i}) for i in range(10)]:
f.write(serialized_sample)
def main():
filename = "test.rec"
if not os.path.exists(filename):
serialize_dummy_recording(filename)
index = index_from_recording(filename)
print(index)
if __name__ == "__main__":
main()
我发现 tell
方法返回 Unpacker
的当前字节偏移量。但是,在删除参数的 latest documentation that I could find. Also the write_bytes
parameter is not declared as deprecated as mentioned in the commit 中没有描述此行为。
创建索引的工作函数现在如下所示:
def index_from_recording(filename):
# create empty index
index = []
with open(filename, "rb") as f:
# create the `msgpack.Unpacker`
unpacker = msgpack.Unpacker(f)
try:
while True:
# add current offset to index
index.append(unpacker.tell())
# unpack (and discard) next item
unpacker.unpack()
except msgpack.OutOfData:
pass
return index
在我的场景中,我需要允许随机访问使用 msgpack 序列化的单个项目。 IE。给定一个二进制文件和一个项目索引,我想跳转到文件中的那个位置并反序列化这个项目。
为了获取每个项目的字节偏移量,我使用 mgspack.Unpacker
的 unpack
函数。在 mgspack 0.5 中,unpack
接受一个可选参数 write_bytes
,它是一个在序列化之前在原始数据字符串上调用的挂钩。计算这个字符串的 len
可以得到项目的大小(以字节为单位),这样我就可以累积字节偏移量。
自 msgpack 0.6 以来,write_bytes
参数不再被接受,我没有找到任何替代品给我 raw 输入字符串或消耗的字节数阅读一个项目后。
这是我用来创建索引的函数。函数 returns 将索引作为字节偏移列表。每个条目 index[i]
都包含项目 i
的字节偏移量。关键部分是 unpacker.unpack(write_bytes=hook)
调用,它不再接受任何属性。
def index_from_recording(filename):
# create empty index
index = []
# hook that keeps track of the byte offset of the `msgpack.Unpacker`
hook = ByteOffsetHook()
with open(filename, "rb") as f:
# create the `msgpack.Unpacker`
unpacker = msgpack.Unpacker(f)
try:
while True:
# add current offset to index
index.append(hook.offset)
# unpack (and discard) next item.
# The `hook` keeps track of the read bytes
unpacker.unpack(write_bytes=hook) # <== `write_bytes` not accepted since 0.6
except msgpack.OutOfData:
pass
return index
ByteOffsetHook
定义如下。钩子简单地计算原始输入字符串的 len
并累积它。
class ByteOffsetHook(object):
def __init__(self):
self.offset = 0
def __call__(self, data):
self.offset += len(data)
为了调试,您可以使用此函数生成虚拟录音。
def serialize_dummy_recording(filename):
with open(filename, "wb") as f:
for serialized_sample in [msgpack.packb({'x': i}) for i in range(10)]:
f.write(serialized_sample)
def main():
filename = "test.rec"
if not os.path.exists(filename):
serialize_dummy_recording(filename)
index = index_from_recording(filename)
print(index)
if __name__ == "__main__":
main()
我发现 tell
方法返回 Unpacker
的当前字节偏移量。但是,在删除参数的 latest documentation that I could find. Also the write_bytes
parameter is not declared as deprecated as mentioned in the commit 中没有描述此行为。
创建索引的工作函数现在如下所示:
def index_from_recording(filename):
# create empty index
index = []
with open(filename, "rb") as f:
# create the `msgpack.Unpacker`
unpacker = msgpack.Unpacker(f)
try:
while True:
# add current offset to index
index.append(unpacker.tell())
# unpack (and discard) next item
unpacker.unpack()
except msgpack.OutOfData:
pass
return index