1

I am wondering the ways to end a worker thread in Python 3.

If you look at this code sample from this question the worker has a while True loop in it and all I see is that q.task_done() is called.

Why is this worker automatically ended?

Specifically I am interested in:

What options exist to end the workers infinite loop?

It seems like the only options would be to call break or return but I am not sure if those even kill the thread.

To be clear I actually want this thread to die when its task has completed and I do not see the ways to kill the thread documented anywhere.

#!python3
import threading
from queue import Queue
import time

# lock to serialize console output
lock = threading.Lock()

def do_work(item):
    time.sleep(.1) # pretend to do some lengthy work.
    # Make sure the whole print completes or threads can mix up output in one line.
    with lock:
        print(threading.current_thread().name,item)

# The worker thread pulls an item from the queue and processes it
def worker():
    while True:
        item = q.get()
        do_work(item)
        q.task_done()

# Create the queue and thread pool.
q = Queue()
for i in range(4):
     t = threading.Thread(target=worker)
     t.daemon = True  # thread dies when main thread (only non-daemon thread) exits.
     t.start()

# stuff work items on the queue (in this case, just a number).
start = time.perf_counter()
for item in range(20):
    q.put(item)

q.join()       # block until all tasks are done

# "Work" took .1 seconds per task.
# 20 tasks serially would be 2 seconds.
# With 4 threads should be about .5 seconds (contrived because non-CPU intensive "work")

print('time:',time.perf_counter() - start)
Community
  • 1
  • 1
Startec
  • 12,496
  • 23
  • 93
  • 160

1 Answers1

1

What options exist to end the workers infinite loop?

Run with the while loop polling a threading.semaphore object instance, rather than a constant True boolean. Signal the semaphore from the killing thread when you want to kill the worker, and it will drop out of the loop.

If you want the main thread to wait for the worker to finish, then signal the semaphore, and then do a thread.join() to block the main thread until the worker has finished doing whatever it needs to do. Just remember to signal the semaphore first, or it will hang ;)

That said, you've daemonized the thread, so you don't need to kill it. The process will die when there are no non-daemon threads left alive. UPDATE To remove the daemon effect as you want the thread to exit cleanly, just remove this line:

t.daemon = True  # thread dies when main thread (only non-daemon thread) exits.
solidpixel
  • 10,688
  • 1
  • 20
  • 33