/ / Deserialice json / yaml desde un flujo binario que contiene otros datos: python, json, serialización, yaml

Deserialice json / yaml del flujo binario que contiene otros datos: python, json, serialización, yaml

Supongamos que tengo un flujo binario stream Y lo genero de la siguiente manera.

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

Entonces, ¿tengo que escribir un analizador personalizado de algún tipo para la secuencia o puedo recuperar some_obj como sigue.

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

Si esto no funciona con la serialización yaml, ¿funciona con la serialización json?

Respuestas

1 para la respuesta № 1

No puedes hacer lo que quieres porque el analizador YAML consume la secuencia completa incluso si no dummp un final explícito (yaml.dump(some_obj, stream, explicit_end=True) (que esencialmente inserta ...n antes de awesome) y tampoco funciona cuando se escribe ---nawesome (El separador de documentos). El analizador YAML consume la palabra awesome¹ tanto cuando usas yaml.load() así como cuando usas yaml.load_all().

La parte delantera funciona bien, así que puedes considerar hacer algo como:

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)

lo que da (en Python2):

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

y los contenidos del archivo son:

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

Utilizo una técnica similar, pero leyendo líneas con for line in stream, que no se puede combinar con lo normal read() operaciones, para archivos que tienen un encabezado YAML con metadatos, seguidos de texto normal (sin sangría para que Emacs pueda trabajar correctamente en él).


¹ Considero leer más allá del marcador de fin de secuencia (...) un error en el analizador Python YAML, así que intentaré solucionarlo en la próxima versión.