Serialización de objetos legibles por humanos de Python
-
03-07-2019 - |
Pregunta
Necesito almacenar estructuras Python hechas de listas / diccionarios, tuplas en un formato legible por humanos. La idea es como usar algo similar a pickle , pero pickle no es amigable para los humanos. Otras opciones que me vienen a la mente son YAML (a través de PyYAML y JSON (a través de simplejson ) serializadores.
¿Alguna otra opción que se te ocurra?
Gracias de antemano.
Solución
Para casos simples, pprint () y eval () vienen a la mente.
Usando su ejemplo:
>>> d = {'age': 27,
... 'name': 'Joe',
... 'numbers': [1,
... 2,
... 3,
... 4,
... 5],
... 'subdict': {
... 'first': 1,
... 'second': 2,
... 'third': 3
... }
... }
>>>
>>> from pprint import pprint
>>> pprint(d)
{'age': 27,
'name': 'Joe',
'numbers': [1, 2, 3, 4, 5],
'subdict': {'first': 1, 'second': 2, 'third': 3}}
>>>
Me lo pensaría dos veces antes de arreglar dos requisitos con la misma herramienta. ¿Ha considerado usar pickle para la serialización y luego pprint () (o un visor de objetos más elegante) para los humanos que miran los objetos?
Otros consejos
Si es solo lista de Python, diccionario y objeto de tupla. - JSON es el camino a seguir. Es legible para los humanos, muy fácil de manejar e independiente del lenguaje.
Precaución: las tuplas se convertirán en listas en simplejson.
In [109]: simplejson.loads(simplejson.dumps({'d':(12,3,4,4,5)}))
Out[109]: {u'd': [12, 3, 4, 4, 5]}
Si busca más representaciones de las que JSON cubre, le recomiendo que revise PyON (notación de objetos de Python) ... aunque creo que está restringido a 2.6 / 3.0 y superior, ya que se basa en el módulo ast . Maneja instancias de clases personalizadas y tipos de datos recursivos, entre otras características, que es más de lo que proporciona JSON.
Debería revisar jsonpickle ( https://github.com/jsonpickle/jsonpickle ). Escribirá cualquier objeto python en un archivo json. Luego puedes leer ese archivo de nuevo en un objeto python. Lo bueno es que el archivo intermedio es muy legible porque es json.
¿Qué quieres decir con que esto no es legible para humanos? ;)
>>> d = {'age': 27,
... 'name': 'Joe',
... 'numbers': [1,2,3,4,5],
... 'subdict': {'first':1, 'second':2, 'third':3}
... }
>>>
>>> import pickle
>>> p = pickle.dumps(d)
>>> p
"(dp0\nS'age'\np1\nI27\nsS'subdict'\np2\n(dp3\nS'second'\np4\nI2\nsS'third'\np5\nI3\nsS'first'\np6\nI1\nssS'name'\np7\nS'Joe'\np8\nsS'numbers'\np9\n(lp10\nI1\naI2\naI3\naI4\naI5\nas."
Ok, bueno, tal vez solo requiera algo de práctica & # 8230; o podrías hacer trampa ...
>>> import pickletools
>>> pickletools.dis(p)
0: ( MARK
1: d DICT (MARK at 0)
2: p PUT 0
5: S STRING 'age'
12: p PUT 1
15: I INT 27
19: s SETITEM
20: S STRING 'subdict'
31: p PUT 2
34: ( MARK
35: d DICT (MARK at 34)
36: p PUT 3
39: S STRING 'second'
49: p PUT 4
52: I INT 2
55: s SETITEM
56: S STRING 'third'
65: p PUT 5
68: I INT 3
71: s SETITEM
72: S STRING 'first'
81: p PUT 6
84: I INT 1
87: s SETITEM
88: s SETITEM
89: S STRING 'name'
97: p PUT 7
100: S STRING 'Joe'
107: p PUT 8
110: s SETITEM
111: S STRING 'numbers'
122: p PUT 9
125: ( MARK
126: l LIST (MARK at 125)
127: p PUT 10
131: I INT 1
134: a APPEND
135: I INT 2
138: a APPEND
139: I INT 3
142: a APPEND
143: I INT 4
146: a APPEND
147: I INT 5
150: a APPEND
151: s SETITEM
152: . STOP
highest protocol among opcodes = 0
>>>
Aún tendría que leer el objeto encurtido de un archivo, sin embargo, no tendría que cargar
. Entonces, si es un " peligroso " objeto, aún puede ser capaz de averiguarlo antes de hacer load
. Si estás atascado con un pickle
, podría ser una buena opción para descifrar lo que tienes.
Para usar simplejson primero easy_install simplejson :
import simplejson
my_structure = {"name":"Joe", "age":27, "numbers":[1,2,3,4,5], "subdict":{"first":1, "second":2, "third": 3}}
json = simplejson.dumps(my_structure)
da como resultado que json sea:
{"age": 27, "subdict": {"second": 2, "third": 3, "first": 1}, "name": "Joe", "numbers": [1, 2, 3, 4, 5]}
Observe que apenas cambia el formato del diccionario, pero debe ejecutar este paso para garantizar que los datos JSON sean válidos.
Puedes seguir imprimiendo el resultado:
import pprint
pprint.pprint(my_structure)
resultados en:
{'age': 27,
'name': 'Joe',
'numbers': [1, 2, 3, 4, 5],
'subdict': {'first': 1, 'second': 2, 'third': 3}}
Hay un formato AXON (textual) que combina el mejor de JSON, XML y YAML. El formato AXON es bastante legible y relativamente compacto.
El módulo python (2.7 / 3.3-3.7) pyaxon admite la carga de ( s)
/ volcado (s)
, incluida la carga iterativa de
/ dumping
. Es lo suficientemente rápido para ser útil.
Considere el ejemplo simple:
>>> d = {
'age': 27, 'name': 'Joe',
'numbers': [1, 2, 3, 4, 5],
'subdict': {'first': 1, 'second': 2, 'third': 3}
}
# pretty form
>>> axon.dumps(d, pretty=1)
{ age: 27
name: "Joe"
numbers: [1 2 3 4 5]
subdict: {
first: 1
second: 2
third: 3}}
# compact form
>>> axon.dumps(d)
{age:27 name:"Joe" numbers:[1 2 3 4 5] subdict:{first:1 second:2 third:3}}
También puede manejar múltiples objetos en el mensaje:
>>> msg = axon.dumps([{'a':1, 'b':2, 'c':3}, {'a':2, 'b':3, 'c':4}])
>>> print(msg)
{a:1 b:2 c:3}
{a:2 b:3 c:4}
{a:3 b:4 c:5}
y luego cárgalos iterativamente:
for d in axon.iloads(msg):
print(d)