serialización - serializacion de objetos python
Serialización de objetos legibles por humanos Python (7)
Para casos simples vienen a la mente pprint () y eval ().
Usando tu 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}}
>>>
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 sofisticado) para los humanos que miran los objetos?
Necesito almacenar las estructuras de Python hechas de listas / diccionarios, tuplas en un formato legible para 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 los serializadores PyYAML y JSON (a través de simplejson ).
¿Alguna otra opción que se te ocurra?
Gracias por adelantado.
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)
resultados en json siendo:
{"age": 27, "subdict": {"second": 2, "third": 3, "first": 1}, "name": "Joe", "numbers": [1, 2, 3, 4, 5]}
Tenga en cuenta que apenas cambia el formato del diccionario, pero debe ejecutarlo a través de este paso para garantizar datos JSON válidos.
Puedes imprimir mejor 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}}
Si es solo una lista de Python, un diccionario y un objeto de tupla. - JSON es el camino a seguir. Es legible por humanos, muy fácil de manejar y también independiente del lenguaje.
Precaución: las tuplas se convertirán a 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 buscas más representaciones que las cubiertas por JSON, te recomiendo que revises PyON (Notación de Objetos Python) ... aunque creo que está restringido a 2.6 / 3.0 y superior, ya que depende del 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 consultar jsonpickle ( http://code.google.com/p/jsonpickle/ ). Escribirá cualquier objeto python en un archivo json. A continuación, puede volver a leer ese archivo 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 por los 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 requiere algo de práctica ... 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
>>>
Todavía tendría que leer el objeto escabechado de un archivo, sin embargo, no necesitaría load
. Por lo tanto, si se trata de un objeto "peligroso", es posible que aún puedas descifrarlo antes de realizar la load
. Si está atascado con un pickle
, podría ser una buena opción para descifrar lo que tiene.
Hay un formato AXON (textual) que combina lo mejor de JSON, XML y YAML. El formato AXON es bastante legible y relativamente compacto.
El pyaxon del módulo python (2.7 / 3.3 / 3.4) admite la funcionalidad de load(s)
/ dump(s)
, incluida la loading
/ dumping
iterativa. Es lo suficientemente rápido para ser útil.
Considera un 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 cargarlos iterativamente:
for d in axon.iloads(msg):
print(d)