karlosos
karlosos

Reputation: 1174

Run thread in loop only if it's not currently running in Python

I'm trying to separate my logic (function or task) from main loop. This function usually takes long time to run. In following example calculate() function takes a lot of time to calculate self.time variable.

In other words I want calculate() to be called asynchronously. In every iteration first I would check if calculate() is running, if not then call it. Secondly I would call show() function in every iteration, no matter if calculate() changed self.time value.

import time
import datetime


class Clock:
    def __init__(self):
        self.time = None

    def calculate(self):
        time.sleep(3)
        self.time = datetime.datetime.now()

    def show(self):
        print(f"{self.time.minute}:{self.time.second}")

    def loop(self):
        while True:
            self.calculate()  # this should be asynchronous
            self.show()  # this should be called every iteration


if __name__ == '__main__':
    clock = Clock()
    clock.loop()

Output:

36:9
36:12
36:15
36:18

This is not a wanted outcome. What I want:

36:9
...
36:9
36:9
36:12
...
36:12
36:15
36:15
36:15
...
36:15
36:18
36:18
...
36:18

How I've tried to solve this (this probably not the best solution, so future reader please check answers):

import time
import datetime
import threading


class Clock:
    def __init__(self):
        self.time = datetime.datetime.now()
        self.__thread = None

    def calculate(self):
        time.sleep(3)
        self.time = datetime.datetime.now()  # race condition?

    def show(self):
        print(f"{self.time.minute}:{self.time.second}")

    def loop(self):
        while True:
            if self.__thread is None or not self.__thread.is_alive():
                self.__thread = threading.Thread(target=self.calculate)
                self.__thread.start()
            self.show()


if __name__ == '__main__':
    clock = Clock()
    clock.loop()

Program output is what I wanted. Is there any flaw in this solution? I can think only of race condition.

I am aware that's not the greatest description of this problem. If you could help me with editing this post with more searchable and specific vocabulary I would be grateful. If you have idea for better title please leave it in comments.

Upvotes: 0

Views: 92

Answers (1)

abdullahalali
abdullahalali

Reputation: 406

I checked your code in my IDE, and it looks like exactly what you wanted using an acceptable approach. The only alternative solution I can think of is: 1) use a temp variable that goes up by one until it gets to 3 then reset. 2) similar idea but use time.nextTime = 3 to jump every 3 seconds and print current time.

Also, your first code solution seems to take some time to run is because it's waiting 3 seconds to show the time. And regarding race condition, that's not an issue since you're not using multiple threads at the same time in your second solution.

Upvotes: 1

Related Questions