Stopping a thread after a certain amount of time

Question:

I’m looking to terminate some threads after a certain amount of time. These threads will be running an infinite while loop and during this time they can stall for a random, large amount of time. The thread cannot last longer than time set by the duration variable.
How can I make it so after the length set by duration, the threads stop.

def main():
    t1 = threading.Thread(target=thread1, args=1)
    t2 = threading.Thread(target=thread2, args=2)

    time.sleep(duration)
    #the threads must be terminated after this sleep
Asked By: Takkun

||

Answers:

This will work if you are not blocking.

If you are planing on doing sleeps, its absolutely imperative that you use the event to do the sleep. If you leverage the event to sleep, if someone tells you to stop while “sleeping” it will wake up. If you use time.sleep() your thread will only stop after it wakes up.

import threading
import time

duration = 2

def main():
    t1_stop = threading.Event()
    t1 = threading.Thread(target=thread1, args=(1, t1_stop))

    t2_stop = threading.Event()
    t2 = threading.Thread(target=thread2, args=(2, t2_stop))

    time.sleep(duration)
    # stops thread t2
    t2_stop.set()

def thread1(arg1, stop_event):
    while not stop_event.is_set():
        stop_event.wait(timeout=5)

def thread2(arg1, stop_event):
    while not stop_event.is_set():
        stop_event.wait(timeout=5)
Answered By: Nix

If you want the threads to stop when your program exits (as implied by your example), then make them daemon threads.

If you want your threads to die on command, then you have to do it by hand. There are various methods, but all involve doing a check in your thread’s loop to see if it’s time to exit (see Nix’s example).

Answered By: Seth

If you want to use a class:

from datetime import datetime,timedelta

class MyThread(): 

    def __init__(self, name, timeLimit):        
        self.name = name
        self.timeLimit = timeLimit
    def run(self): 
        # get the start time
        startTime = datetime.now()
    
        while True:
           # stop if the time limit is reached :
           if((datetime.now()-startTime)>self.timeLimit):
               break
           print('A')

mt = MyThread('aThread',timedelta(microseconds=20000))
mt.run()
Answered By: Nora_F

An alternative is to use signal.pthread_kill to send a stop signal. While it’s not as robust as @Nix’s answer (and I don’t think it will work on Windows), it works in cases where Events don’t (e.g., stopping a Flask server).

test.py

from signal import pthread_kill, SIGTSTP
from threading import Thread

import time

DURATION = 5


def thread1(arg):
    while True:
        print(f"processing {arg} from thread1...")
        time.sleep(1)


def thread2(arg):
    while True:
        print(f"processing {arg} from thread2...")
        time.sleep(1)


if __name__ == "__main__":
    t1 = Thread(target=thread1, args=(1,))
    t2 = Thread(target=thread2, args=(2,))

    t1.start()
    t2.start()
    time.sleep(DURATION)
    # stops all threads
    pthread_kill(t2.ident, SIGTSTP)

result

$ python test.py
processing 1 from thread1...
processing 2 from thread2...
processing 1 from thread1...
processing 2 from thread2...
processing 1 from thread1...
processing 2 from thread2...
processing 1 from thread1...
processing 2 from thread2...
processing 1 from thread1...
processing 2 from thread2...

[19]+  Stopped                 python test.py
Answered By: reubano
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.