Search code examples
pythonmultithreadingpython-multithreading

Maintain an auto-cleanable list of threads in Python


I maintain a threads list, and I want to auto-remove threads from the list when they are finished.

I found this method:

import threading, time

def f(seconds, info):
    print('starting', seconds)
    time.sleep(seconds)
    print('finished', seconds)
    threads.remove(info['thread'])

def newaction(seconds):
    info = {}
    thread = threading.Thread(target=f, args=(seconds, info))
    info['thread'] = thread
    thread.start()
    threads.append(thread)

threads = []
newaction(1)
newaction(2)
for _ in range(10):
    time.sleep(0.3)
    print(threads)

It works:

starting 1
starting 2
[<Thread(Thread-1, started 1612)>, <Thread(Thread-2, started 712)>]
[<Thread(Thread-1, started 1612)>, <Thread(Thread-2, started 712)>]
[<Thread(Thread-1, started 1612)>, <Thread(Thread-2, started 712)>]
finished 1
[<Thread(Thread-2, started 712)>]
[<Thread(Thread-2, started 712)>]
[<Thread(Thread-2, started 712)>]
finished 2
[]
[]
[]
[]

But the fact of having to pass a dict info is a bit a hack. I used it because obviously I can't pass thread in args...

thread = threading.Thread(target=f, args=(seconds, thread))  
#                                                     ^ not created yet!

...when the Thread object is not created yet!

Is there a more natural way in Python to maintain an auto-cleanable list of threads?


Solution

  • You have the current_thread() function.

    import threading, time
    
    def f(seconds):
        print('starting', seconds)
        time.sleep(seconds)
        print('finished', seconds)
        threads.remove(threading.current_thread())
    
    def newaction(seconds):
        thread = threading.Thread(target=f, args=(seconds,))
        thread.start()
        threads.append(thread)
    
    threads = []
    newaction(1)
    newaction(2)
    for _ in range(10):
        time.sleep(0.3)
        print(threads)
    

    Output:

    starting 1
    starting 2
    [<Thread(Thread-1, started 4588)>, <Thread(Thread-2, started 4388)>]
    [<Thread(Thread-1, started 4588)>, <Thread(Thread-2, started 4388)>]
    [<Thread(Thread-1, started 4588)>, <Thread(Thread-2, started 4388)>]
    finished 1
    [<Thread(Thread-2, started 4388)>]
    [<Thread(Thread-2, started 4388)>]
    [<Thread(Thread-2, started 4388)>]
    finished 2
    []
    []
    []
    []