Как сериализовать python dict в текст в удобочитаемом виде?

У меня есть python dict, ключи и значения которого представляют собой строки, целые числа и другие словари и кортежи (json их не поддерживает). Я хочу сохранить его в текстовый файл, а затем прочитать его из файла. По сути, мне нужен read аналог встроенного в print (как в Lisp).

Ограничения:

  1. файл должен быть удобочитаемым (поэтому pickle отсутствует)
  2. нет необходимости обнаруживать цикличности.

Есть ли что-нибудь лучше, чем json?


person sds    schedule 20.01.2015    source источник
comment
Что, по вашему мнению, может сделать что-то лучше, чем json?   -  person BrenBarn    schedule 21.01.2015
comment
@BrenBarn: read соответствует print   -  person sds    schedule 21.01.2015
comment
@sds, что вы имеете в виду, читать для ввода, печатать для вывода ... это две принципиально разные вещи   -  person Joran Beasley    schedule 21.01.2015
comment
см. print и читать   -  person sds    schedule 21.01.2015
comment
Честно говоря, json — это ваш ответ, и именно поэтому он был принят менее чем за 5 лет. Какие проблемы с разборчивостью есть у json? Существует множество утилит json indenter и pretty-printer — используйте их, и они удобочитаемы. json также чрезвычайно эффективен.   -  person smci    schedule 21.01.2015
comment
@smci: да, боюсь, мне придется придерживаться json   -  person sds    schedule 21.01.2015
comment
@sds: честно говоря, это блестяще. Просто найдите хороший индентер/красивый принтер, который вам нравится, свяжите его с типом файла .json, и вы никогда не оглянетесь назад. Существует множество молниеносно быстрых и производительных json-библиотек. «Удобочитаемость» — это всего лишь психологическое препятствие. У меня была такая же реакция, как и у вас, когда я впервые увидел его.   -  person smci    schedule 21.01.2015


Ответы (2)


Вы можете использовать repr() для dict, затем прочитать его и проанализировать с помощью ast.literal_eval(). Он так же удобочитаем, как и сам Python.

Пример:

In [1]: import ast

In [2]: x = {}

In [3]: x['string key'] = 'string value'

In [4]: x[(42, 56)] = {'dict': 'value'}

In [5]: x[13] = ('tuple', 'value')

In [6]: repr(x)
Out[6]: "{(42, 56): {'dict': 'value'}, 'string key': 'string value', 13: ('tuple', 'value')}"

In [7]: with open('/tmp/test.py', 'w') as f: f.write(repr(x))

In [8]: with open('/tmp/test.py', 'r') as f: y = ast.literal_eval(f.read())

In [9]: y
Out[9]:
{13: ('tuple', 'value'),
 'string key': 'string value',
 (42, 56): {'dict': 'value'}}

In [10]: x == y
Out[10]: True

Вы также можете рассмотреть возможность использования модуля pprint для еще более удобного форматированного вывода.

person user108471    schedule 20.01.2015
comment
стоит отметить, что simplejson на несколько порядков быстрее, чем это, хотя это немного быстрее, чем наивное json - person Joran Beasley; 21.01.2015
comment
@JoranBeasley Приятно знать. Я не могу придумать ничего другого, что было бы так же просто реализовать, как JSON, и так же удобочитаемо для человека. - person user108471; 21.01.2015
comment
Учитывая неспособность json обрабатывать ключи кортежа, это кажется единственным ответом. Спасибо. - person sds; 27.01.2015
comment
Если вывод repr() для вас недостаточно красив, вы также можете рассмотреть функцию pprint из модуля pprint, которая предназначена для более удобной печати объектов python. Вывод pprint() может быть легко проанализирован ast.literal_eval(). - person user108471; 27.01.2015

Честно говоря, json - это ваш ответ [РЕДАКТИРОВАТЬ: пока ключи являются строками, я не видел часть о dicts как ключах], и поэтому он был принят менее чем за 5 лет. Какие проблемы с разборчивостью есть у json? Существует множество json-инденторов, утилит для печати изображений, плагинов для браузеров [1][2] — используйте их, и это, безусловно, удобочитаемо для человека. json(/simplejson) также чрезвычайно эффективен (реализации C), он масштабируется и может обрабатываться последовательно, чего нельзя сказать о подходе AST (зачем быть эксцентричным и нарушать масштабируемость?).

Это также, кажется, консенсус 100% людей, отвечающих вам здесь ... все не могут ошибаться ;-) XML мертв, скатертью дорога.

  1. Как я могу красиво распечатать JSON? и многие другие
  2. Подключаемые модули JSON для браузера
person smci    schedule 20.01.2015
comment
извините, json - ваш ответ BS - person sds; 27.01.2015
comment
@sds: вам нужно объяснить, почему, вы не можете просто опубликовать ругательство. Что бы это ни стоило, я экспериментировал с другими форматами в течение пары лет, пока с неохотой не пришел к такому же выводу. На то есть очень веские причины (более быстрый синтаксический анализ, производительность, стандартизация, куча сторонних инструментов/утилит/библиотек). - person smci; 27.01.2015
comment
@sds Также вам нужно сформулировать лучший метод: подход AST OP или что-то еще? - person smci; 27.01.2015
comment
Ссылка ясно объясняет, что json не может сериализовать довольно много объектов. - person sds; 27.01.2015
comment
У меня нет лучшего метода; если бы делал - не спрашивал бы здесь. Однако json не может быть ответом. Возможно, можно было бы написать сериализатор на основе json, но простое использование json.dump определенно не является ответом на вопрос о сериализации. - person sds; 27.01.2015
comment
Итак: JSON поддерживает только строки в качестве ключей, кортежи/списки/дикты/наборы/произвольные объекты не допускаются. Потребуется обходной путь. Зависит от того, что такое ключи OP. См. Лучший способ кодирования кортежей с помощью json. - person smci; 27.01.2015
comment
Нет, это не зависит от моих фактических данных. Сериализация означает универсальность. Это означает, что любой объект, который может быть осмысленно сохранен и восстановлен, должен обрабатываться без проблем (например, я не прошу возможности сохранять/восстанавливать потоки). - person sds; 27.01.2015