我正在将我的应用程序从py27“移植”到py33。 在大多数情况下,这是非常微不足道的。那说py27和amp;之间有一个非常奇怪的区别。 py33
我基本上有两个线程,他们通过队列进行通信。 发送的数据类型如下:
TX_Queue.put((3,'SOME_TAG',{some:type,of:data})
即优先级,命令,数据
这在py27中运行得非常好,但是现在大部分转换为py33已经完成了我不时会得到一个奇怪的例外:
return heappop(self.queue)
TypeError: unorderable types: dict() < dict()
任何想法是关于PriorityQueues这是py27和py3之间的变化是什么?
答案 0 :(得分:8)
与PriorityQueue
s无关;改变的内容与dict
有关,更常见的是对没有自然排序的对象进行排序。
问题是你正在尝试对包含dicts的两个元组进行排序,如下所示:
(3, 'SOME_TAG', {'some': 'type', 'of': 'data'})
元组按字典顺序比较 - 也就是说,它们首先比较第一个元素,如果它们相等,则尝试第二个元素,如果它们相等,则尝试第三个元素,依此类推。
大多数情况下,第一个或第二个元素会有所不同,所以你不需要比较第三个元素,所以一切都会好的。
但偶尔会有两个这样的值:
(3, 'SOME_TAG', {'some': 'type', 'of': 'data'})
(3, 'SOME_TAG', {'some': 'othertype', 'with': 'differentdata'})
然后,它需要比较两个dicts来决定哪个元组更少。
这是一件毫无意义的事情。词典的项目本质上是无序的,那么你如何决定哪一个比另一个少呢?事实上,即使 是项目的固定且可预测的元素,您在此期望的规则是什么?第一个减少是因为'of' < 'with'
吗?或更大,因为'other type' < 'type'
?还是...?
Python 2.x只做一些随意而无用的事情; Python 3.x反而引发异常。这在Ordering Comparisons的“3.x中的新内容”文档中记录:
当操作数没有有意义的自然时,排序比较运算符(
<
,<=
,>=
,>
)会引发TypeError
异常排序。
所以,你在这些情况下已经遇到了问题,但是Python 2.x通过偶尔默默地做一些无用的事情来隐藏问题,而3.x使问题显而易见。
那么,解决方案是什么?那么,你想要发生什么?我的猜测是你实际上想要排序第一个元素,忽略其他元素。在这种情况下,你在Python 2.x中自动获得接近的东西,而你可能没有注意到它有时会以不可预测的方式不稳定。但如果您真的想要这种行为,那么在两个版本中,您都必须自己编写。
不幸的是,与Python中大多数与排序相关的函数和对象不同,PriorityQueue
不使用key
函数。*这意味着您必须手动“装饰 - 排序 - 未装饰”。但这并不难。例如:
class TupleSortingOn0(tuple):
def __lt__(self, rhs):
return self[0] < rhs[0]
def __gt__(self, rhs):
return self[0] > rhs[0]
def __le__(self, rhs):
return self[0] <= rhs[0]
def __ge__(self, rhs):
return self[0] >= rhs[0]
然后你可以这样做:
TX_Queue.put(TupleSortingOn0(3,'SOME_TAG',{some:type,of:data}))
*因为它使用了heapq
,并且heapq
无法处理密钥,因为“正常列表中运行的函数”的设计排除了它...