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()