lezebulon
lezebulon

Reputation: 7994

Potential bug in heapq.heappush?

I'm trying to understand if the following snippet doesn't exhibit a bug in heapq.heappush :

import heapq

x = []
heapq.heappush(x, 1)
print(x)
try:
    heapq.heappush(x, "a")
except:
    pass

print(x) # [1, 'a']

Here, I'm trying to build a heap with non-comparable items. As expected, the second call to heappush is throwing an exception. However, I notice that the second item was inserted in the array anyway. This array was supposed to always contain a heap, and now it isn't a heap anymore.

Shouldn't heappush method undo the insert of "a" in case it can't finish the heapify process on insertion ?

Consider the case where you have a multi-threaded system relying on this. Assume I have some workers that are dequeueing from the heap, and some worker processes that are inserting in the heap. This means that if a worker is incorrectly inserting an invalid type, the worker will raise an excpetion as expected, but the underlying data-structure is still corrupted

Upvotes: 2

Views: 149

Answers (1)

relent95
relent95

Reputation: 4730

Although it may be opinionated to some degree, I believe most other Python veterans will agree with me.

No it's not a bug. When an exception occurs in a function or method, there's no guarantee that the state of the variables is restored to the previous one. You can also see this for the core API list.sort() in the following example.

a = [2, 1, 4, 'a', 4, 3]
try:
    a.sort()
except:
    pass
print(a)
# This will output "[1, 2, 4, 'a', 4, 3]".

As a side note, putting non-comparable objects into a priority queue is an abnormal operation, usually a mistake by a programmer, which is a candidate for an assertion. If the library has to handle this case, it will be inefficient for the users because most of the time the additional code will be dead code and will be a burden to the maintainer.

Upvotes: 3

Related Questions