2017 年 6 月 8 日更新
虽然 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)))))
结果:
(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 - 删除下划线(但不确定这是否总是有效)
那么是什么导致了pickle字典排序下的谜团呢?
证明在 dict 上调用 sort 会提供转储以产生相同的结果:
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."