Reputation: 531
I'm trying to use the multiprocessing library in python 2.7 and I found the behaviour of time.sleep() function a little bit disturbing. I need to control a timing critical hardware (on Raspberry PI) and my initial goal was to use a process dedicated to this using this library. But I found that putting the main process to sleep (time.sleep) also put the child process to sleep!?!? Is this the normal behaviour or I'm missing something? Here an exemple of code that reproduce my problem :
import time
from multiprocessing import Process, Queue
def child(q_display):
c = 9999999
while True:
data = q_display.get()
print data
print c
c = c - 1
if __name__ == '__main__':
q_display = Queue()
p = Process(target=child, args=(q_display,)).start()
data = 1
try:
while True:
q_display.put(data)
data = data + 1
print "MAIN ***********************************"
time.sleep(1)
except KeyboardInterrupt:
print "Keyboard CTRL-C !!!"
The output is this :
MAIN ***********************************
1
9999999
MAIN ***********************************
2
9999998
MAIN ***********************************
3
9999997
MAIN ***********************************
4
9999996
MAIN ***********************************
5
9999995
MAIN ***********************************
6
9999994
But this is what I expected:
MAIN ***********************************
1
9999999
9999998
9999997
9999996
9999995
9999994
9999993
9999992
MAIN ***********************************
2
9999991
9999990
9999989
9999988
9999987
9999986
9999985
9999984
... etc
What is I'm doing wrong?
Upvotes: 2
Views: 2159
Reputation: 18488
The problem is that Queue.get()
blocks until there is some item available in the queue. By passing a timeout parameter to the get()
function, and catching the corresponding error (this needs a from Queue import Empty
), you can continue doing other stuff in the child process even if the main process did not send anything yet. Change the code in your child function to this:
while True:
try:
data = q_display.get(True, timeout=0.1) # can raise Empty after 0.1 s
print data
except Empty: # queue was empty, next time better
pass
print c
c = c - 1
This seems to do more or less what you want:
MAIN ***********************************
MAIN ***********************************1
9999999
[...]
9999990
2
MAIN ***********************************
9999989
9999988
[...]
9999980
3
MAIN ***********************************
9999979
[...]
9999970
4
MAIN ***********************************
9999969
[...]
9999960
5
MAIN ***********************************
9999959
[...]
9999950
6
Keyboard CTRL-C !!!
9999949
[...]
9999943
Note that the printouts of the main and the child process can get messed up a bit, they are not an accurate way to monitor the exact timing of the events due to buffering issues.
Upvotes: 1
Reputation: 1031
I think the issue is that you're sleeping in the loop that's putting data into the queue. So there is only one value in the queue before your main process sleeps, and therefore the child can only read one out before it blocks.
Upvotes: 0