Сериализация читаемого человеком Python объекта - PullRequest
24 голосов
/ 03 января 2009

Мне нужно хранить структуры Python из списков / словарей, кортежей в удобочитаемом формате. Идея похожа на использование чего-то похожего на рассол , но рассол не удобен для человека. Другие варианты, которые мне приходят на ум, это сериалы YAML (через PyYAML и JSON (через simplejson ).

Любой другой вариант, который приходит на ум?

Заранее спасибо.

Ответы [ 7 ]

18 голосов
/ 03 января 2009

Для простых случаев на ум приходят 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 () (или более интересный просмотрщик объектов) для людей, смотрящих на объекты?

14 голосов
/ 03 января 2009

Если его просто Список Python, словарь и объект кортежа. - JSON это путь. Его удобочитаемо, очень легко в обращении и не зависит от языка.

Внимание: кортежи будут преобразованы в списки в simplejson.

In [109]: simplejson.loads(simplejson.dumps({'d':(12,3,4,4,5)}))
Out[109]: {u'd': [12, 3, 4, 4, 5]}
4 голосов
/ 28 февраля 2010

Вы должны проверить jsonpickle (https://github.com/jsonpickle/jsonpickle).. Он запишет любой объект python в файл json. Затем вы можете прочитать этот файл обратно в объект python. Приятно то, что промежуточный файл очень читабелен, потому что это JSON.

4 голосов
/ 06 января 2009

Если вам нужно больше представлений, чем предусмотрено JSON, я настоятельно рекомендую проверить PyON (нотация Python) ... хотя я считаю, что он ограничен 2.6 / 3.0 и выше, так как опирается на модуль ast . Он обрабатывает экземпляры пользовательских классов и рекурсивные типы данных, помимо других функций, что больше, чем обеспечивает JSON.

3 голосов
/ 04 апреля 2015

Что вы имеете в виду, что это не читается человеком ??? ;)

>>> 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, это может быть хорошим вариантом для расшифровки того, что у вас есть.

2 голосов
/ 03 января 2009

Для использования 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}}
0 голосов
/ 04 апреля 2015

Существует AXON (текстовый) формат, сочетающий в себе best JSON, XML и YAML. Формат AXON довольно читабелен и относительно компактен.

Модуль python (2.7 / 3.3-3.7) 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)
...