从包含其他数据的二进制流反序列化json / yaml

时间:2016-06-01 23:46:36

标签: python json serialization yaml

假设我有一个二进制流stream,我按如下方式生成它。

stream.write('lol'.encode())
yaml.dump(some_obj, stream)
stream.write('awesome'.encode())

那么我是否必须为流编写某种自定义解析器,或者我可以按如下方式恢复some_obj

stream.read(3)
recovered = yaml.load(stream)
stream.read(7)

如果这不适用于yaml序列化,它是否适用于json序列化?

1 个答案:

答案 0 :(得分:1)

你无法做你想做的事,因为YAML解析器会消耗完整的流,即使你明显结束了yaml.dump(some_obj, stream, explicit_end=True)(基本上在...\n之前插入awesome)并且它也没有在编写---\nawesome(文档分隔符)时工作。当您使用awesome时以及使用yaml.load()时,YAML解析器都会使用单词yaml.load_all()¹。 / p>

预备部分工作正常,因此您可以考虑执行以下操作:

import ruamel.yaml as yaml

file_name = 'test.comb'

some_obj = dict(a = [1, 2], b = {3: 42})

with open(file_name, 'w') as stream:
    stream.write('lol'.encode())
    yaml.dump(some_obj, stream, explicit_end=True)
    stream.write('awesome'.encode())


with open(file_name) as stream:
    assert stream.read(3) == 'lol'
    stream_data = ''
    while True:
        stream_data += stream.read(1)
        if stream_data[-4:] == '...\n':
            break
    recovered = yaml.load(stream_data)
    assert stream.read(7) == 'awesome'

print(recovered)

给出(在Python2中):

{'a': [1, 2], 'b': {3: 42}}

,文件内容为:

lola: [1, 2]
b: {3: 42}
...
awesome

我使用类似的技术,但是对于具有带元数据的YAML标头的文件,读取带有for line in stream的行,这些行不能与正常read()操作组合,后跟普通文本(非缩进)所以emacs可以正常使用它。)

¹我考虑在Python YAML解析器中读取流末尾标记(...)中的错误,因此我将尝试在下一个版本中修复此问题。 < / p>