Python Thread Scheduling: Managing Multi-threaded Programs with sched Module

Learn about Python's multi-threading capabilities and how thread scheduling is managed by the host OS. Explore task scheduling in Python using the sched module for automating tasks and running scheduled events in your applications.



Python - Thread Scheduling

Python supports multiple threads in a program. A multi-threaded program can execute multiple sub-tasks independently, allowing parallel execution of tasks.

Python interpreter maps Python thread requests to either POSIX/pthreads or Windows threads. Hence, Python threads are handled by the host operating system like ordinary threads.

However, there is no support for thread scheduling in the Python interpreter. Thread priority, scheduling schemes, and thread pre-emption are not possible with the Python interpreter. The scheduling and context switching of Python threads depend on the host scheduler.

Python has some support for task scheduling through the sched module in the standard library. It can be used to create bots and other monitoring and automation applications. The sched module implements a generic event scheduler for running tasks at specific times, similar to task schedulers in Windows or Linux.

Scheduler Class

The scheduler class is defined in the sched built-in module:

Syntax
scheduler(timefunc=time.monotonic, delayfunc=time.sleep)

Methods defined in the scheduler class include:

  • scheduler.enter() - Schedule events to run after a delay or at a specific time.
  • scheduler.cancel() - Remove an event from the queue. Raises a ValueError if the event is not in the queue.
  • scheduler.run(blocking=True) - Run all scheduled events.

To schedule events with a delay, use the enter() method, which takes four arguments:

  • A number representing the delay
  • A priority value
  • The function to call
  • A tuple of arguments for the function

Example 1

This example schedules two different events:

Code

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def schedule_event(name, start):
    now = time.time()
    elapsed = int(now - start)
    print('elapsed=', elapsed, 'name=', name)

start = time.time()
print('START:', time.ctime(start))
scheduler.enter(2, 1, schedule_event, ('EVENT_1', start))
scheduler.enter(5, 1, schedule_event, ('EVENT_2', start))

scheduler.run()
            
Output

START: Mon Jun 5 15:37:29 2023
elapsed= 2 name= EVENT_1
elapsed= 5 name= EVENT_2
            

Example 2

Another example to understand the concept better:

Code

import sched
from datetime import datetime
import time

def addition(a, b):
    print("Performing Addition:", datetime.now())
    print("Time:", time.monotonic())
    print("Result:", a + b)

s = sched.scheduler()

print("Start Time:", datetime.now())

event1 = s.enter(10, 1, addition, argument=(5, 6))
print("Event Created:", event1)
s.run()
print("End Time:", datetime.now())
            
Output

Start Time: 2023-06-05 15:49:49.508400
Event Created: Event(time=774087.453, priority=1, sequence=0, action=, argument=(5, 6), kwargs={})
Performing Addition: 2023-06-05 15:49:59.512213
Time: 774087.484
Result: 11
End Time: 2023-06-05 15:49:59.559659