Nihar
Nihar

Reputation: 53

How to stop a multithreaded function inside the function from running after a certain amount of time in Python?

I am doing an AI project, where I am using a genetic algorithm to implement the "Letters and Number", where we are given a list of numbers and the process tries to calculate the nearest value to the target by using the genetic algorithm.

For the analysis part, I want to run my program for 2 seconds and then stop and check how many generations did it ran.

The function that I am using is

def task2():
    Q = [100, 50, 3, 3, 10, 75]
    target = 533
    pop_list = []
    for i in range(20):
        r = random.randint(5, 1000)
        pop_list.append(r)
    start=time.time()
    PERIOD_OF_TIME = 2
    v, T = evolve_pop(Q, target,
                     max_num_iteration = 200,
                    population_size = 200 ,
                parents_portion = 0.3)
    if stop_event.is_set():
        cost = v
        print("cost: ", cost)
    print(time.time() - start)
    print(pop_list)

if __name__ == '__main__':
    # We create another Thread
    action_thread = Thread(target=task2)
    # Here we start the thread and we wait 5 seconds before the code continues to execute.
    action_thread.start()
    action_thread.join(timeout=2)
    # We send a signal that the other thread should stop.
    stop_event.set()
    print("Hey there! I timed out! You can do things after me!")

The result is:

After 117 generations, the best individual has a cost of 1
After 118 generations, the best individual has a cost of 1
After 119 generations, the best individual has a cost of 1
After 120 generations, the best individual has a cost of 1
Hey there! I timed out! You can do things after me!
After 121 generations, the best individual has a cost of 1
After 122 generations, the best individual has a cost of 1
After 123 generations, the best individual has a cost of 1
After 124 generations, the best individual has a cost of 1
After 125 generations, the best individual has a cost of 1

Since the evolve_pop() is another function inside the tesk2() which still carries on even after 2 seconds. I want to know, is there any way to exit out of evolve pop after 2 seconds/ the statement Hey there! I timed out! You can do things after me! is printed.

The expected result

After 117 generations, the best individual has a cost of 1
After 118 generations, the best individual has a cost of 1
After 119 generations, the best individual has a cost of 1
After 120 generations, the best individual has a cost of 1
Hey there! I timed out! You can do things after me!

I tried using exit(), quit() and sys.exit(0) but non of them seems to stop the function from keep on printing.

Upvotes: 0

Views: 117

Answers (2)

AKX
AKX

Reputation: 169388

With just Python's built-in bits, no, you can't interrupt a "non-cooperating" function from another thread.

There is a library on PyPI called stopit that can inject an exception into another thread, which would basically do what you want.

Upvotes: 0

ziirish
ziirish

Reputation: 106

As threads share memory, usually you can interract with other threads by updating a variable. Something like:

running = False

def my_long_runnging_code():
    while running:
        # do something here

if __name__ == "__main__":
    thread = Thread(target=my_long_running_code)
    running = True
    thread.start()
    # we wait a bit
    time.sleep(2)
    # now we tell the thread to stop iterating
    running = False
    # it will still finish it's current computation
    thread.join()

Alternatively, if you don't need to share memory with your computation code, you can use python multiprocessing instead which offers a way to interrupt your code at any time:

import time
import multiprocessing

def my_long_running_code():
    # doing something long

if __name__ == "__main__":
    p = multiprocessing.Process(target=my_long_running_code)
    p.start()
    time.sleep(2)
    p.terminate()

Upvotes: 1

Related Questions