The timesched
Python module provides a simple time event scheduler. It
is implemented upon the standard Python
sched
module and is
used in a similar way, but provides a nicer and more modern and
convenient programming interface. Apart from normal oneshot and repeat
timers, it can run timers at a given time of day, and for the given days
of week, providing simple cron-like functionality. It requires only
Python 3.6 or later, and the standard library. The latest version of
this document and code is available at
https://github.com/bulletmark/timesched.
class timesched.Scheduler(timefunc=time.time, delayfunc=time.sleep)
Refer to the class description for Python sched.scheduler which is used in the internal implementation of this class.
Scheduler instances have the following methods.
oneshot(time, priority, func, *args, **kwargs)
- time: expiry time relative to now, or absolute time. Type can be one of:
int
at given relative seconds after now,datetime.timedelta()
at given relativetimedelta()
after now,datetime.time()
at giventime()
after now,datetime.datetime()
at given absolutedatetime()
,datetime.date()
at given absolutedate()
,
- priority: int value, lower value is higher priority. Refer description.
- func and args and kwargs: user function and arguments to call when timer is invoked.
Returns a timer ID which can be used to cancel the timer using
cancel(timer)
.
repeat(period, priority, func, *args, **kwargs)
- period: period for timer. Type can be one of:
int
at each given seconds after now,datetime.timedelta()
at each giventimedelta()
after now,datetime.time()
at giventime()
each day after now. E.g. at 10:30 every day for simple daily "cron-like" functionality.
- priority: int value, lower value is higher priority. Refer description.
- func and args and kwargs: user function and arguments to call when timer is invoked.
Returns a timer ID which can be used to cancel the timer using
cancel(timer)
.
Note that for int and timedelta() periods, the specified period is the delay between the end of the callback function and when it is called again so the actual period will slowly "creep" by the run time of the callback. Many applications are not concerned about this distinction but if necessary you can instead invoke a oneshot() absolute timer between each call.
Call this with time = datetime.time()
to invoke a oneshot()
at the
given time on the next day from the set of given days of the week.
oneshot_on_days(days, time, priority, func, *args, **kwargs)
-
days: A list/set/sequence/range of integers 0-6 where 0 = Monday to 6 = Sunday. e.g. [0] means only invoke timer on a Monday, [0,6] = only invoke on Monday and Sunday, etc. Using
days=range(7)
is same as calling ordinaryoneshot()
.Alternately, you can specify days as a string "MTWTFSS" where each char is upper case if the day is to be set, and lower case if not. E.g. "MTWTFss" is the working week Mon-Fri, "mtwTfss" is Thu only, etc. A utility function to explicitly parse this string into a set of integers is available as
timesched.parse_days(string_arg)
if you need. -
time:
datetime.time()
for given time on the next given day.
Remaining parameters and return type are same as oneshot()
.
Call this with time = datetime.time()
to invoke a repeat()
at the
given period on each of the given days of the week.
repeat_on_days(days, period, priority, func, *args, **kwargs)
-
days: parameter same as
oneshot_on_days()
. -
period:
datetime.time()
for given time on the given days.
Remaining parameters and return type are same as repeat()
.
count()
Returns the count of timers currently active. A timer is considered active while it is pending and until it's callback function has completed, unless it is explicitly cancelled.
cancel(timer)
Remove the timer with timer
ID. If the timer is not currently active,
this method will raise a ValueError.
run(blocking=True)
Invokes the base scheduler.run()
. Refer full
description at Python sched
module.
#!/usr/bin/python3
'Very simple examples'
import timesched
from datetime import datetime, time
# Job function to be called for each timer
def job(jobid):
print(f'Job {jobid} called at {datetime.now()}')
# Create a scheduler
s = timesched.Scheduler()
# Execute job() once in 5 secs time
s.oneshot(5, 0, job, 1)
# Execute job() every 2 secs
s.repeat(2, 0, job, 2)
# Execute job() at 10:30am every work day (not weekends)
s.repeat_on_days('MTWTFss', time(10, 30), 0, job, 3)
# Run scheduler, will block until no timers left running
s.run()
The timesched
module is internally implemented using the standard
Python sched
module
but differs in the following ways. Note that the sched
implementation,
methods, and attributes are not directly exposed in the public interface.
- Provides
oneshot()
andrepeat()
methods to conveniently accept standarddatetime.datetime()
,datetime.date()
,datetime.time()
,datetime.timedelta()
, and also integer time arguments, based automatically on the type of the passed time argument. - The
repeat()
method sets itself up to be automatically invoked again at the next repeat interval, unlikesched
which only provides aoneshot()
equivalent method [i.e.enter()
orenterabs()
] so the user does not need to explicitly set up the next timer. - Provides a convenient way to schedule a timer at a given time each
day to give simple daily "cron-like" functionality, e.g.
s.repeat(datetime.time(hour=10, minute=30), f)
to periodically activate a timer at 10:30 every day. - Further to the above
repeat()
which can run at a given time every day, you can userepeat_on_days()
to specify a given time on a set of given days, e.g.s.repeat_on_days('MTWTFss', datetime.time(hour=10, minute=30), f)
to run the timer at 10:30 each workday only (Mon to Fri). Alternatelys.repeat_on_days(range(5), datetime.time(hour=10, minute=30), f)
gives the same result. - Consistent with modern Python, allows user to plainly specify
*args
and**kwargs
directly in timer setup call rather than in a tuple as legacysched
requires. - Does not provide the
enter()
orenterabs()
methods. Use the superioroneshot()
,repeat()
,oneshot_on_days()
, orrepeat_on_days()
methods instead. - Provides a more specific
count()
method instead ofempty()
. - Does not provide the
queue
attribute. - Uses
time.time
instead oftime.monotonic
as the defaulttimefunc
for the internal scheduler. This is to be compatible withdatetime.datetime.timestamp()
which is used internally.
Arch Linux users can install timesched from the AUR.
timesched
is available on PyPI
so install the usual way, e.g:
pip3 install timesched
Or explicitly from github:
git clone https://github.com/bulletmark/timesched.git
cd timesched
sudo pip3 install .