Home > OS >  Python - Run multiple functions at different time interval inside loop
Python - Run multiple functions at different time interval inside loop

Time:09-06

So I want to make a loop like this (example simplified):

def main():
 while True:
  function1() #run this every 1s
  function2() #run this every 2s
  function3() #run this every 5s
  function4() #run this every 10s

Ideally, after 10s it should run function1 10 times, function2 5 times, function3 2 times,..etc.

My current approach is using a loop counter but it's far from ideal since the time spent for each loop is not accounted and is not constant.

def main():
 while True:
  loop_counter = loop_counter   1
  if loop_counter % 2 == 0: function1()
  if loop_counter % 4 == 0: function2()
  if loop_counter % 10 == 0: function3()
  if loop_counter % 20 == 0: function4()
  #this assumes each loop take 0.5s to run

I'm new to python so any guidance is appreciated.

CodePudding user response:

You can use python schedule library. Docs here.

import schedule
def main():
  schedule.every(1).seconds.do(function1)
  schedule.every(2).seconds.do(function2)
  schedule.every(5).seconds.do(function3)
  schedule.every(10).seconds.do(function4)
  while True:
    schedule.run_pending()
    time.sleep(1)

CodePudding user response:

Using threading.Timer:

from threading import Timer
from time import monotonic


def run_every_n_secs(fn, n):
    start = monotonic()
    fn()
    elapsed = monotonic() - start
    Timer(n, lambda: run_every_n_secs(fn, max(n - elapsed, 0))).start()


def main():
    run_every_n_secs(function1, 1)
    run_every_n_secs(function2, 2)
    run_every_n_secs(function3, 5)
    run_every_n_secs(function4, 10)

Or if you don't mind having the same function running in parallel with itself (if e.g. function1 might take longer than a second to run but you want to start it every second anyway), you can start the timer for the next iteration before calling the function:

from threading import Timer

def run_every_n_secs(fn, n):
    Timer(n, lambda: run_every_n_secs(fn, n)).start()
    fn()
  • Related