How to schedule a periodic task that is immune to changing system time using Python

I am using the python schedule module to run a task periodically and I think I ran into a problem.

I believe that it relies on the time of the system on which the python script is running. For example, let's say that I want to run a task every 5 seconds. If I forward the system time, the scheduled task will run as expected. However, if I rewind the system time to, say, 1 day, then the next scheduled task will be completed in 5 seconds + 1 day.

If you run the script below and then change the system time to a few days ago, you can reproduce the problem. The problem can be reproduced on Linux and Windows.

import sched import time import threading period = 5 scheduler = sched.scheduler(time.time, time.sleep) def check_scheduler(): print time.time() scheduler.enter(period, 1, check_scheduler, ()) if __name__ == '__main__': print time.time() scheduler.enter(period, 1, check_scheduler, ()) thread = threading.Thread(target=scheduler.run) thread.start() thread.join() exit(0) 

Does anyone have a python solution around this problem?

+5
source share
1 answer

From scheduled documentation :

class sched.scheduler (timefunc, delayfunc)

The scheduler class defines a common interface for scheduling events. It needs two functions to really deal with the "external world" - timefunc should be called without arguments and return a number ("time", in any units). The delayfunc function must be called with a single argument compatible with the timefunc output, and it must delay this many time units. delayfunc will also call with argument 0 after the start of each event, to allow other threads to work in multi-threaded applications.

The problem is that your code uses time.time() as a timefunc , the return value of which (when called without arguments) is the current system time and is thus prone to overloading the system clock.

In order for your code to be immune to changes in system time, you need to provide a timefunc that does not depend on system time, start time / current time, etc.

You can write your own function, for example, return the number of seconds from the moment your process starts, which you will need to actually read in your code (i.e. not compute it based on timeline deltas). The time.clock() function can help if it is based on processor time counters, but I'm not sure if this is true or not.

+3
source

Source: https://habr.com/ru/post/1247640/


All Articles