泡菜序列化顺序之谜



2017年8月6日更新

尽管3年过去了,我的PR仍然是一个临时解决方案,通过执行输出命令。Stream Framework可能会重新考虑其使用内容作为通知密钥的设计。GitHub第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)))))

结果:

(dp0nS'deal_url'np1nS'J'np2nsS'order_number'np3nS'X'np4ns.
(dp0nS'order_number'np1nS'X'np2nsS'deal_url'np3nS'J'np4ns.
(dp0nS'deal_url'np1nS'J'np2nsS'order_number'np3nS'X'np4ns.

显然,每个转储的序列化输出都会发生变化。当我从任何一个关键帧中删除一个角色时,都不会发生这种情况。我发现这是因为Stream Framework使用pickle输出作为在其k/v存储中存储通知的密钥。如果我们能更好地了解这里发生的事情,我会撤回请求。我找到了两种解决方案来防止它:

A-排序后转换为字典(是的,不知何故提供了预期的副作用)

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

B-删除下划线(但不确定这是否总是有效的)

那么,是什么导致了pickle字典排序的神秘性呢?

通过dict调用sort提供转储以产生相同结果的证据:

import operator
x = dict(sorted(x.iteritems(), key=operator.itemgetter(1)))
pickle.dumps(x)
"(dp0nS'order_number'np1nS'X'np2nsS'deal_url'np3nS'J'np4ns."
x = pickle.loads(pickle.dumps(x))
x = dict(sorted(x.iteritems(), key=operator.itemgetter(1)))
pickle.dumps(x)
"(dp0nS'order_number'np1nS'X'np2nsS'deal_url'np3nS'J'np4ns."

Dictionary是未排序的数据结构。这意味着顺序是任意的,pickle将按原样存储它们。如果您想使用排序字典,可以使用collections.OrderedDict

当你在翻译里玩的时候,你认为你看到的任何命令都只是翻译对你表现得很好。

来自dict:的文档

最好将字典视为一组无序的键:值对,要求键是唯一的(在一个字典中)

请记住,函数dict.keys()dict.values()dict.items()也按任意顺序返回各自的值。

相关内容

  • 没有找到相关文章

最新更新