python-cookbook icon indicating copy to clipboard operation
python-cookbook copied to clipboard

Communicating between threads example

Open torsi-uptown opened this issue 11 years ago • 1 comments

Hi!

In the Chapter 12: communicating between threads "Solution" section (bottom of p493) there is an example in which the Queue.task_done method is used along with Queue.join to wait for all items produced by the "producer" function to be consumed.

However (and unless I am misunderstanding), because the queue has no items in it before the threads start, unless the producer function immediately puts an item (before the q.join() executes in the main thread) into the queue, the queue will immediately join. For example, if you have something like:

from queue import Queue
from threading import Thread
import time

def producer(out_q):
    time.sleep(5)
    out_q.put('hello')

def consumer(in_q):
    h = in_q.get()
    print(h + ' world!')
    in_q.task_done()

q = Queue()
t1 = Thread(target=producer, args=(q,))
t2 = Thread(target=consumer, args=(q,))

t1.start()
t2.start()

q.join()
print('q joined!')

You will see:

q joined!
hello world!

I guess the fix would be putting in an initial sentinel before starting the threads?

Love the book by the way!

torsi-uptown avatar Jun 15 '13 18:06 torsi-uptown

This is a good observation. Another possible fix is to join with the producer thread before performing the task join operation. I'll make a note in text for errata.

Cheers Dave

Sent from cell

On Jun 15, 2013, at 1:11 PM, drewthepooh [email protected] wrote:

Hi!

In the Chapter 12: communicating between threads "Solution" section (bottom of p493) there is an example in which the Queue.task_done method is used along with Queue.join to wait for all items produced by the "producer" function to be consumed.

However (and unless I am misunderstanding), because the queue has no items in it before the threads start, unless the producer function immediately puts an item (before the q.join() executes in the main thread) into the queue, the queue will immediately join. For example, if you have something like:

from queue import Queue from threading import Thread import time

def producer(out_q): time.sleep(5) out_q.put('hello')

def consumer(in_q): h = in_q.get() print(h + ' world!') in_q.task_done()

q = Queue() t1 = Thread(target=producer, args=(q,)) t2 = Thread(target=consumer, args=(q,))

t1.start() t2.start()

q.join() print('q joined!') You will see:

q joined! hello world! I guess the fix would be putting in an initial sentinel value before starting the threads?

— Reply to this email directly or view it on GitHub.

dabeaz avatar Jun 15 '13 20:06 dabeaz