Сериализация понятных пользователем Python объектов
Мне нужно хранить структуры Python из списков/словарей, кортежи в читаемый человеком формат. Идея похожа на использование чего-то похожего на pickle, но рассол не дружелюбен для человека. Другие варианты, которые мне приходят, YAML (через PyYAML и JSON (через simplejson) сериализаторы.
Любой другой вариант, который приходит вам на ум?
Спасибо заранее.
Ответы
Ответ 1
Для простых случаев приходят на ум pprint() и eval().
Используя ваш пример:
>>> 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}}
>>>
Я бы дважды подумал об исправлении двух требований с помощью одного и того же инструмента. Рассматривали ли вы использование pickle для сериализации, а затем pprint() (или более привлекательного зрителя объектов) для людей, смотрящих на объекты?
Ответ 2
Если это только список Python, словарь и кортеж. - JSON - это путь. Его читаемость на людях, очень простая в обращении и независимая от языка.
Внимание: кортежи будут преобразованы в списки в simplejson.
In [109]: simplejson.loads(simplejson.dumps({'d':(12,3,4,4,5)}))
Out[109]: {u'd': [12, 3, 4, 4, 5]}
Ответ 3
Если вы больше других представлений, чем описано в JSON, я настоятельно рекомендую проверить PyON (Python Object Notation)... Хотя я считаю, что он ограничен 2.6/3.0 и выше, поскольку он полагается на модуль ast. Он обрабатывает экземпляры специальных экземпляров и рекурсивные типы данных, среди других функций, что больше, чем обеспечивается JSON.
Ответ 4
Вы должны проверить jsonpickle (http://code.google.com/p/jsonpickle/). Он выведет любой объект python в json файл. Затем вы можете прочитать этот файл обратно в объект python. Приятно, что файл inbetween очень читаем, потому что он json.
Ответ 5
Что вы имеете в виду, это не читается человеком?;)
>>> 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."
Хорошо, может, это просто требует некоторой практики... или вы можете обмануть...
>>> 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
>>>
Вам все равно придется читать маринованный объект из файла, однако вам не нужно его load
. Итак, если это "опасный" объект, вы все равно сможете это понять, прежде чем делать load
. Если вы застряли с pickle
, это может быть хорошим вариантом для расшифровки того, что у вас есть.
Ответ 6
Чтобы использовать simplejson сначала 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)
приводит к тому, что json:
{"age": 27, "subdict": {"second": 2, "third": 3, "first": 1}, "name": "Joe", "numbers": [1, 2, 3, 4, 5]}
Обратите внимание, что он практически не изменил формат словаря, но вы должны запустить его с помощью этого шага, чтобы обеспечить достоверность данных JSON.
Вы можете еще более печально распечатать результат:
import pprint
pprint.pprint(my_structure)
приводит к:
{'age': 27,
'name': 'Joe',
'numbers': [1, 2, 3, 4, 5],
'subdict': {'first': 1, 'second': 2, 'third': 3}}
Ответ 7
Существует AXON (текстовый) формат, который объединяет лучший JSON, XML и YAML.
Формат AXON довольно читабельен и относительно компактен.
Модуль python (2.7/3.3/3.4) pyaxon поддерживает функциональность load(s)
/dump(s)
, включая итеративный loading
/dumping
. Это достаточно быстро, чтобы быть полезным.
Рассмотрим простой пример:
>>> 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}}
Он также может обрабатывать несколько сообщений в сообщении:
>>> 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}
а затем загрузите их итеративно:
for d in axon.iloads(msg):
print(d)