0

I have two functions: foo() should start every 5 seconds and bar() should start every 10 seconds. code below:

import threading
import time


def foo():
    while True:
        time.sleep(5)
        print("Call every 5 seconds")
        time.sleep(5)

def bar():
    while True:
        time.sleep(10)
        print("Call every 10 seconds")


tr1 = threading.Thread(target=foo)
tr1.start()
tr2 = threading.Thread(target=bar)
tr2.start()

But I think that this is not a good solution. What is the best way to do this? And yes, I think that I have memory leak, should I use garbage collector or anything else?

P.S. I hope you could understand what i wrote, because I am not native speaker.

  • 1
    The first function is also being called after 10 seconds. – Ajay Brahmakshatriya May 03 '17 at 19:42
  • 3
    _"But I think that this is not a good solution"_. Why do you think that? _"I think that I have memory leak"_. Why do you think that? – Kevin May 03 '17 at 19:43
  • 2
    Possible duplicate of [What is the best way to repeatedly execute a function every x seconds in Python?](http://stackoverflow.com/questions/474528/what-is-the-best-way-to-repeatedly-execute-a-function-every-x-seconds-in-python) – depperm May 03 '17 at 19:44
  • Why do you call `time.sleep(5)` twice in the first function? – Barmar May 03 '17 at 19:58
  • If you consider `bar` alone and if `bar` did substantially more work than just printing a single line then the starting time of execution of that work would *not* be every ten seconds (it would be more than ten seconds and the interval could be irregular). – Bill Bell May 03 '17 at 20:44

2 Answers2

1

Using the link posted by depperm in the comments

import sched, time
s = sched.scheduler(time.time, time.sleep)

def foo(s):
    print("Call every 5 seconds")
    s.enter(5, 1, foo, (s,))

def bar(s):
    print("Call every 10 seconds")
    s.enter(10, 1, bar, (s,))

s.enter(5, 1, foo, (s,))
s.enter(10, 1, bar, (s,))
s.run()
Community
  • 1
  • 1
Diego Amicabile
  • 579
  • 4
  • 12
  • You may want to add `from datetime import datetime` and then change the print to `print("Call every 10 seconds", datetime.now().strftime('%H:%M.%S'))` – boardrider May 04 '17 at 10:13
0

Your code with minor changes, plus some print statements that suggest that this works alright. The 'good' thing about this code is that sleep will raise an exception if the argument to it is negative. Thus, if the codes expected to take less than five or ten seconds respectively take longer then then script will die.

import threading
import time
from datetime import timedelta, datetime

def foo(delay=5):
    while True:
        t_start = time.time()
        print("Call every %s seconds" % delay, datetime.now().strftime('%H.%M.%S'))
        t_end = time.time()
        time.sleep(delay-(t_end-t_start))

def bar(delay=10):
    while True:
        t_start = time.time()
        print("Call every %s seconds" % delay, datetime.now().strftime('%H.%M.%S'))
        t_end = time.time()
        time.sleep(delay-(t_end-t_start))

tr1 = threading.Thread(target=foo)
tr1.start()
tr2 = threading.Thread(target=bar)
tr2.start()

Here's the output.

>pythonw -u "temp1.py"
Call every 5 seconds 17.09.51
Call every 10 seconds 17.09.51
Call every 5 seconds 17.09.56
Call every 5 seconds 17.10.01
Call every 10 seconds 17.10.01
Call every 5 seconds 17.10.06
Call every 5 seconds 17.10.11
Call every 10 seconds 17.10.11
Call every 5 seconds 17.10.16
Call every 5 seconds 17.10.21
Call every 10 seconds 17.10.21
Call every 5 seconds 17.10.26
Call every 10 seconds 17.10.31
Call every 5 seconds 17.10.31
Call every 5 seconds 17.10.36

>Process failed to respond; forcing abrupt termination...
>Exit code: 1

I cannot say whether this is the 'best' way of doing this. At least the contents of the functions begin at more or less regular time intervals.

Bill Bell
  • 21,021
  • 5
  • 43
  • 58