How to run Python function every 1 minute, without using time.Leep()

Asked

Viewed 827 times

1

Is it possible to run a function every 1 minute without using the.Sleep() team? I need to use the computer clock so that, whenever the clock reaches 1 minute, the function is executed. The.Leep() team did not serve because it became difficult to synchronize the start of the program at 0:00 so that the 60-second time interval would match the one on the clock.

tried that code:

while True:
    agora = datetime.datetime.now()
    segundo = agora.strftime('%S')
    if segundo == '00':
        print(agora)

Then I tried this other code, but also unsuccessfully:

while True:
    agora = datetime.datetime.now()
    hora = agora.strftime('%M:%S')
    zero = ['1:00', '2:00', '3:00', '4:00', '5:00', '6:00', '7:00', '8:00', '9:00', '0:00']
    if agora in zero:
        print(agora)
  • Have you seen the module Sched?

  • between the calls from the scheduled functions you will run something? (even if you have a graphical user interface like Tkinter, this is considered "run something")

1 answer

2

How @Jassriver put it there - the module can be used sched from the standard library - but only this tip may not be enough, since "sched" is very low-level and flexible - so requires building a little code "around" to work well -

So, for starters, the builder sched.schedule asks as parameters the pause functions and tell the time - all it does is, once it is called his "run" method - it goes calling the pause functions and checking the time and calling the scheduled events. The simplest way to use it is to pass the functions time.time and time.pause for Scheduler - and this implies that you will have to schedule the events using the unit of time used by "time.time" - which is a single integer representing the number of seconds elapsed since 0h00 on January 1, 1970.

To schedule minutes, then we have to use the Python datetime module to convert the round minutes in these "Unix timestamp" - and then schedule an event for each minute.

Also, after calling the ". run", Scheduler will keep calling the "team.Sleep" and your program will do nothing else. This can be remedied by calling the Scheduler ". run()" in another thread.

I’ll set a minimal example here - ...

import sched
import time
import threading
from datetime import datetime


def repeat_at_interval(scheduler, event, interval=60, add_n=10, start_t=None):
    """Adds 'add_n' more calls to "event" at each "interval" seconds"""
    # Unix timestamp
    if start_t is None:
        t = time.time()
        # round to next interval -
        t = t - (t % interval) + interval
    else:
        t = start_t

    for i in range(add_n):
        scheduler.enterabs(t, 0, event)
        t += interval

    # Schedule call to self, to add "add_n" extra events
    # when these are over:
    scheduler.enterabs(t - interval, 0, repeat_at_interval, kwargs={
        "scheduler": scheduler,
        "event": event,
        "interval": interval,
        "add_n": add_n,
        "start_t": t
        })


def test():
    print (datetime.now())

def main():
    scheduler  = sched.scheduler(time.time, time.sleep)
    repeat_at_interval(scheduler, test, interval=60)
    thread = threading.Thread(target=scheduler.run)
    thread.start()
    while True:

        time.sleep(10)
        # Qualquer outro código para rodar em paralelo,
        # pode ficar aqui -
        # as tarefas agendadas são chamadas em outra
        # thread
        print("controle")


if __name__ == "__main__":
    main()

Note that I made the accounts for the calls without using the datetime module, which allows you to do accounts using "hour, minute, second, day of the month, month, year" - etc -- and direct use of the time.time() - notice that if I get the rest of the division of "time.time()" by 60, I have the last-minute round timestamp (counting from the 1970-1-1 "epoch" 00.00) -and from then on, if I’m always adding "60" in that amount, I’ll have the other minutes.

Using the timestamp makes the code not have to do "accounts", and "ifs" for the time, day, date, etc... (if I were using datetime objects, I could, to calculate the time of the next minute proximo = previo.replace(minute = previo.minuto + 1) - but then you’d have to take into account all the changes - in the 59th minute, the 23rd hour, the 31st, etc...)

Another cool thing about this code is that instead of adding "a million" calls at once, it creates 10, and calls the function itself that schedules events at the end of those 10 - and then schedules another 10. If you were using a framework that allows you to schedule a callback for in "x seconds", like Tkinter, pyglet, pyqt, etc... in general the event itself "schedules" back. This feature lets your event not have to worry about it.

  • Excellent. I did not know the sched module, but I have already started to study it. Your answer opened my possibilities.

  • it should be easy to find external libraries that have all this ready too- sorry I didn’t quote.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.