I'd like to understand how to use the optional parameter blocking
in the method scheduler.run(blocking=True)
. Any practical/real-world example would be very helpful.
Based on the research I've done so far, the intention of the blocking
optional argument is for non-blocking or async applications[1][2]. Below is the main run loop of the schduler (from the python 3.6 library sched.py
). Following through the code, I notice that whenever blocking
is set to False
, immediately returns the time difference between target time and current time, unless the target time had passed, in which case the action would be executed.
while True:
with lock:
if not q:
break
time, priority, action, argument, kwargs = q[0]
now = timefunc()
if time > now:
delay = True
else:
delay = False
pop(q)
if delay:
if not blocking:
return time - now
delayfunc(time - now)
else:
action(*argument, **kwargs)
delayfunc(0) # Let other threads run
Seems to me the non-blocking design requires me to keep running the scheduler until the queue is clean. Thus, I'm thinking about maintaining a task queue myself and keep pushing the scheduler.run
task into the queue (like the code below.) Is this a desirable design? What is the proper way of using the non-blocking scheduler?
def action():
print('action at: ', datetime.now())
if __name__ == '__main__':
s = sched.scheduler(time.time)
target_time = datetime.now() + timedelta(seconds=5)
s.enterabs(target_time.timestamp(), 1, action)
run = functools.partial(s.run, blocking=False)
taskq = deque()
taskq.append(run)
while taskq:
task = taskq.popleft()
result = task()
print(result)
if result:
taskq.append(run)
time.sleep(1)
print('end tasks')
[1] What’s New In Python 3.3
[2] Issue13449: sched - provide an "async" argument for run() method
The sched module defines a class which implements a general purpose event scheduler: class sched. scheduler(timefunc=time.monotonic, delayfunc=time.sleep) The scheduler class defines a generic interface to scheduling events.
Schedule lets you run Python functions (or any other callable) periodically at pre-determined intervals using a simple, human-friendly syntax. Schedule Library is used to schedule a task at a particular time every day or a particular day of a week. We can also set time in 24 hours format that when a task should run.
To run your python scheduler you will need to create a task, create an action, add the path to your python executable file and to your python script and add a trigger to schedule your script.
Sched module is the standard library, can be used in the creation of bots and other monitoring and automation applications. The sched module implements a generic event scheduler for running tasks at specific times.
Old question, but I just implemented something which used the nonblocking version pretty effectively.
When blocking = True
in sched.scheduler.run
, it will call the delayfunc for the time difference until the next event.
This may be undesirable if your application, at t = 0
, schedules an event A
for t = 10
, but another thread, at t = 1
, schedules an event B
for t = 5
. In this case,
s = sched.scheduler(time.time)
# Spawn threads which enter A and B into s
while True:
s.run(True)
if your main thread is just calling sched.scheduler.run(blocking=True)
in a loop, at t = 0
it will call delayfunc(10)
because it only sees that it has 10 time units left until A
. The main thread won't wake up until t = 10, at which point it will see that it missed B
, run B
5 time units late, and then run A
after B
.
To solve this, you can change the main thread to look like this:
s = sched.scheduler(time.time)
# Spawn threads which enter A and B into s
while True:
next_ev = s.run(False)
if next_ev is not None:
time.sleep(min(1, next_ev))
else:
time.sleep(1)
This code will catch up on all present events, then sleep until the next event, or if there is no next event or if the next event is too far ahead, will sleep for 1 second.
Ideally, scheduler would be implemented with a condition variable for if a new event reaches the front of the priority queue, and it could wait on that variable instead of just sleeping until the next event. This would be the most efficient and most time accurate.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With