我正在将我的应用程序从 py27“移植”到 py33。 在大多数情况下,这是非常微不足道的。那就是说我在 py27 和 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 之间发生了什么变化吗?
最佳答案
与PriorityQueue
相关的内容没有变化;更改的内容与 dict
有关,更普遍的是对没有自然顺序的对象进行排序。
问题是您正在尝试对包含字典的两个元组进行排序,如下所示:
(3, 'SOME_TAG', {'some': 'type', 'of': 'data'})
元组按字典顺序比较——也就是说,它们首先比较第一个元素,如果相等,则尝试第二个元素,如果相等,则尝试第三个,依此类推。
大多数时候,第一个或第二个元素会有所不同,因此您永远不需要比较第三个元素,所以一切都会好起来的。
但偶尔,您会得到两个这样的值:
(3, 'SOME_TAG', {'some': 'type', 'of': 'data'})
(3, 'SOME_TAG', {'some': 'othertype', 'with': 'differentdata'})
然后,它需要比较两个字典来决定哪个元组少。
这是一件毫无意义的事情。字典的项目本质上是无序的,那么您如何确定哪一项比另一项少呢?事实上,即使项目有固定且可预测的元素,您在这里期望的规则是什么?第一个少是因为'of' < 'with'
?或更大,因为 'other type' < 'type'
?或者……?
Python 2.x 只是做一些随意且无用的事情; Python 3.x 改为引发异常。这记录在 Ordering Comparisons 下在“3.x 的新增功能”文档中:
The ordering comparison operators (
<
,<=
,>=
,>
) raise aTypeError
exception when the operands don’t have a meaningful natural ordering.
所以,在这些情况下你已经遇到了问题,但是 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
不处理键,因为“在普通列表上工作的函数”的设计排除了它……
关于python3 queue.PriorityQueue 变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21768493/