Checking on a thread / remove from list

Question:

I have a thread which extends Thread. The code looks a little like this;

class MyThread(Thread):
    def run(self):
        # Do stuff

my_threads = []
while has_jobs() and len(my_threads) < 5:
    new_thread = MyThread(next_job_details())
    new_thread.run()
    my_threads.append(new_thread)

for my_thread in my_threads
    my_thread.join()
    # Do stuff

So here in my pseudo code I check to see if there is any jobs (like a db etc) and if there is some jobs, and if there is less than 5 threads running, create new threads.

So from here, I then check over my threads and this is where I get stuck, I can use .join() but my understanding is that – this then waits until it’s finished so if the first thread it checks is still in progress, it then waits till it’s done – even if the other threads are finished….

so is there a way to check if a thread is done, then remove it if so?

eg

for my_thread in my_threads:
    if my_thread.done():
        # process results
        del (my_threads[my_thread]) ?? will that work...
Asked By: Wizzard

||

Answers:

you need to call thread.isAlive()to find out if the thread is still running

As TokenMacGuy says, you should use thread.is_alive() to check if a thread is still running. To remove no longer running threads from your list you can use a list comprehension:

for t in my_threads:
    if not t.is_alive():
        # get results from thread
        t.handled = True
my_threads = [t for t in my_threads if not t.handled]

This avoids the problem of removing items from a list while iterating over it.

Answered By: Arlaharen

Better way is to use Queue class:
http://docs.python.org/library/queue.html

Look at the good example code in the bottom of documentation page:

def worker():
    while True:
        item = q.get()
        do_work(item)
        q.task_done()

q = Queue()
for i in range(num_worker_threads):
     t = Thread(target=worker)
     t.daemon = True
     t.start()

for item in source():
    q.put(item)

q.join()       # block until all tasks are done
Answered By: seriyPS

The answer has been covered, but for simplicity…

# To filter out finished threads
threads = [t for t in threads if t.is_alive()]

# Same thing but for QThreads (if you are using PyQt)
threads = [t for t in threads if t.isRunning()]
Answered By: Dre
mythreads = threading.enumerate()

Enumerate returns a list of all Thread objects still alive.
https://docs.python.org/3.6/library/threading.html

Answered By: William DeCook

A easy solution to check thread finished or not. It is thread safe

Install pyrvsignal

pip install pyrvsignal

Example:

import time
from threading import Thread
from pyrvsignal import Signal


class MyThread(Thread):
    started = Signal()
    finished = Signal()

    def __init__(self, target, args):
        self.target = target
        self.args = args
        Thread.__init__(self)

    def run(self) -> None:
        self.started.emit()
        self.target(*self.args)
        self.finished.emit()


def do_my_work(details):
    print(f"Doing work: {details}")
    time.sleep(10)

def started_work():
    print("Started work")
    
def finished_work():
    print("Work finished")

thread = MyThread(target=do_my_work, args=("testing",))
thread.started.connect(started_work)
thread.finished.connect(finished_work)
thread.start()
Answered By: Ravikirana B
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.