The code below places three numbers in a queue. Then it attempts to get the numbers back from the queue. But it never does. How to get the data from the queue?
import multiprocessing
queue = multiprocessing.Queue()
for i in range(3):
queue.put(i)
while not queue.empty():
print queue.get()
I originally deleted this answer after I read @Martijn Pieters', since he decribed the "why this doesn't work" in more detail and earlier. Then I realized, that the use case in OP's example doesn't quite fit to the canonical sounding title of
That's not because there's no child process involved for demonstration, but because in real applications hardly ever a queue is pre-filled and only read out after, but reading and writing happens interleaved with waiting times in between. The extended demonstration code Martijn showed, wouldn't work in the usual scenarios, because the while loop would break too soon when enqueuing doesn't keep up with reading. So here is the answer reloaded, which is able to deal with the usual interleaved feeds & reads scenarios:
Don't rely on queue.empty checks for synchronization.
Either use
for msg in iter(queue.get, sentinel):
to.get()
from the queue, where you break out of the loop by passing a sentinel value...iter(callable, sentinel)?...or use
get_nowait()
and handle a possiblequeue.Empty
exception if you need a non-blocking solution.In case only one process and only one thread within this process is reading the queue, it would be also possible to exchange the last code snippet with:
Since a thread could drop the GIL in between checking
if not queue.empty()
andqueue.get()
, this wouldn't be suitable for multi-threaded queue-reads in a process. The same applies if multiple processes are reading from the queue.For single-producer / single-consumer scenarios, using a
multiprocessing.Pipe
instead ofmultiprocessing.Queue
would be sufficient and more performant, though.Your code actually works, some of the time.
That's because the queue is not instantly not empty. The implementation is a bit more involved to support communication between multiple processes, so threads and pipes are involved that cause the
empty
state to last a little longer than your code allows for.See the note in the Pipes and Queues section:
(bold emphasis mine)
If you add a loop to check for emptyness first then your code works:
When you run the above, most of the time the
'queue is still empty'
appears once. Sometimes it doesn't appear at all, and sometimes it'll be printed twice.Check
queue
before usingget
: