Загадка порядка сериализации рассола

Обновление 8/8/17

Несмотря на то, что прошло 3 года, мой PR по-прежнему рассматривается как временное решение, обеспечивающее порядок вывода. Stream-Framework может пересмотреть свой дизайн на использование контента в качестве ключа для уведомлений. GitHub Issue # 153 ссылается на это.

Вопрос

Смотрите следующий образец:

import pickle
x = {'order_number': 'X', 'deal_url': 'J'}

pickle.dumps(x)
pickle.dumps(pickle.loads(pickle.dumps(x)))
pickle.dumps(pickle.loads(pickle.dumps(pickle.loads(pickle.dumps(x)))))

Результаты:

(dp0\nS'deal_url'\np1\nS'J'\np2\nsS'order_number'\np3\nS'X'\np4\ns.
(dp0\nS'order_number'\np1\nS'X'\np2\nsS'deal_url'\np3\nS'J'\np4\ns.
(dp0\nS'deal_url'\np1\nS'J'\np2\nsS'order_number'\np3\nS'X'\np4\ns.

Понятно, что сериализованный вывод изменяется для каждого дампа. Когда я удаляю персонажа из любого ключа, этого не происходит. Я обнаружил это, поскольку Stream-Framework использует маринованный вывод в качестве ключа для хранения уведомлений в своем хранилище k/v. Я потяну запрос, если мы получим лучшее понимание того, что здесь происходит. Я нашел два решения, чтобы предотвратить это:

A - Преобразовать в словарь после сортировки (да, каким-то образом обеспечивает предполагаемый побочный эффект)

import operator
sorted_x = dict(sorted(x.iteritems(), key=operator.itemgetter(1)))

B - Удалить подчеркивания (но не уверен, что это всегда работает)

Так что же вызывает загадку при сортировке словаря для рассола?

Доказательство того, что вызов sort over dict обеспечивает dump для получения того же результата:

import operator
x = dict(sorted(x.iteritems(), key=operator.itemgetter(1)))

pickle.dumps(x)
"(dp0\nS'order_number'\np1\nS'X'\np2\nsS'deal_url'\np3\nS'J'\np4\ns."

x = pickle.loads(pickle.dumps(x))
x = dict(sorted(x.iteritems(), key=operator.itemgetter(1)))

pickle.dumps(x)
"(dp0\nS'order_number'\np1\nS'X'\np2\nsS'deal_url'\np3\nS'J'\np4\ns."

1 ответ

Решение

Словари являются несортированными структурами данных. Это означает, что порядок является произвольным, и рассол будет хранить их как они есть. Вы можете использовать collections.OrderedDict если вы хотите использовать отсортированный словарь.

Любой приказ, который вы видите, когда играете в переводчике, - это просто переводчик, играющий с вами хорошо.

Из документации dict:

Лучше всего рассматривать словарь как неупорядоченный набор пар ключ: значение с требованием, чтобы ключи были уникальными (в пределах одного словаря)

Помните, что функции dict.keys(), dict.values() а также dict.items() также вернуть их соответствующие значения в произвольном порядке.

Другие вопросы по тегам