Jiew Meng
Jiew Meng

Reputation: 88367

Can I get an item from a PriorityQueue without removing it yet?

I want to get the next item in queue but I don't want to dequeue it. Is it possible in Python's queue.PriorityQueue? From the docs, I don't see how can it be done

Upvotes: 61

Views: 97231

Answers (7)

Stephen C
Stephen C

Reputation: 2036

TL;DR -- If you are are using the top item multiple times in a multithreaded environment, you should assign the item to a variable.


The above answers show how to access the elements of a PriorityQueue, however there is some danger when accessing objects from the inner queue in a multithreaded manner (as mentioned at the end of HYRY's answer).

While holding onto the queue object would be even less threadsafe, because that queue object is "live" (see this answer), you can still run into issues when accessing the objects on the queue if you expect the object ordering to be static.

Here's an example:

from queue import PriorityQueue          
import threading                         
import time                              
                                         
pq = PriorityQueue()                     
                                         
def queue_manip():                       
    i = 0                                
    while True:                          
        pq.put((i, i))                   
        i -= 1                           
        time.sleep(.1)                   
                                         
t1 = threading.Thread(target=queue_manip)
t1.start()                               
                                         
while True:                              
    print('FirstAccess:  ', pq.queue[0]) 
    time.sleep(.2)  # other processing   
    print('SecondAccess: ', pq.queue[0]) 
    time.sleep(.2)  # other processing   
    print()                              

which will print something like the below:

FirstAccess:   (0, 0)  
SecondAccess:  (-1, -1)
                       
FirstAccess:   (-3, -3)
SecondAccess:  (-5, -5)
                       
FirstAccess:   (-7, -7)
SecondAccess:  (-9, -9)

For this reason, if you want to use an object from the top of a PriorityQueue, you should assign that object to a name:

from queue import PriorityQueue          
import threading                         
import time                              
                                         
pq = PriorityQueue()                     
                                         
def queue_manip():                       
    i = 0                                
    while True:                          
        pq.put((i, i))                   
        i -= 1                           
        time.sleep(.1)                   
                                         
t1 = threading.Thread(target=queue_manip)
t1.start()                               
                 
while True:                           
    priority, item = pq.queue[0]      
    print('FirstUse:  ', item)        
    time.sleep(.2)  # other processing
    print('SecondUse: ', item)        
    time.sleep(.2)  # other processing
    print()                           
                                      

which will give you:

FirstUse:   0
SecondUse:  0

FirstUse:   -3
SecondUse:  -3

FirstUse:   -7
SecondUse:  -7

Upvotes: 0

Victor Juliet
Victor Juliet

Reputation: 1092

If you want next element in the PriorityQueue, in the order of the insertion of the elements, use:

for i in range(len(queue.queue)):
    print queue.queue[i]

this will not pop anything out.

If you want it in the priority order, use:

for i in range(len(queue.queue)):
    temp = queue.get()
    queue.put(temp)
    print temp

If you are using a tuple, instead of a single variable, replace temp by:

((temp1,temp2))

Upvotes: 9

ahsan naeem
ahsan naeem

Reputation: 275

If q is the PeriorityQueue, then you can use:

for i in range(q.qsize()):
    print(q.queue[i])

Upvotes: 1

hamster ham
hamster ham

Reputation: 749

Assuming your items stored in the PriorityQueue is a tuple (priority, value),

def peek(pq):
  return pq.queue[0][1] 

Upvotes: 4

HYRY
HYRY

Reputation: 97331

If a is a PriorityQueue object, You can use a.queue[0] to get the next item:

from queue import PriorityQueue

a = PriorityQueue()

a.put((10, "a"))
a.put((4, "b"))
a.put((3,"c"))

print(a.queue[0])
print(a.queue)
print(a.get())
print(a.queue)
print(a.get())
print(a.queue)

output is :

(3, 'c')
[(3, 'c'), (10, 'a'), (4, 'b')]
(3, 'c')
[(4, 'b'), (10, 'a')]
(4, 'b')
[(10, 'a')]

but be careful about multi thread access.

Upvotes: 76

Aayush Kumar
Aayush Kumar

Reputation: 1618

Indexing the first element of the queue should work. If you're using the heapq library, the document mentions:

The interesting property of a heap is that its smallest element is always the root, heap[0].

Upvotes: 3

Neel
Neel

Reputation: 21317

When you get item form the queue as per theory it will remove from the queue. You have to write your own function which will give you last element of PriorityQueue. You can create a peek function by inherit the priorityqueue.

Upvotes: 2

Related Questions