Python Basics: Test Scheduled Event Order with a Virtual Clock
A scheduler test does not need real sleeping. Supplying a virtual clock makes deadlines, priorities, and cancellation deterministic while leaving the event queue behavior intact.
Prepare a scratch directory
Tested on Linux with CPython 3.12.14. You need Bash, a text editor, the named runtime, and standard mktemp, rm, and rmdir utilities. Run Python without -O so assertions remain enabled. The examples use only controlled local data; generated fixture directories are cleaned automatically.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1Run the example
Save this as demonstrate-sched.py:
import sched
now = [0.0]
seen = []
def delay(seconds):
now[0] += seconds
def record(label):
seen.append(label)
print(f"{now[0]:.0f}: {label}")
queue = sched.scheduler(lambda: now[0], delay)
queue.enterabs(5, 2, record, argument=("normal",))
queue.enterabs(5, 1, record, argument=("urgent",))
cancelled = queue.enterabs(3, 1, record, argument=("cancelled",))
queue.cancel(cancelled)
queue.enterabs(1, 1, record, argument=("early",))
queue.run()
assert seen == ["early", "urgent", "normal"]
assert queue.empty() and now[0] == 5
print("Queue empty:", queue.empty())Run it:
python3 -B demonstrate-sched.pyObserved output:
1: early
5: urgent
5: normal
Queue empty: TrueRead the result
The injected delay function advances time instead of sleeping. The earlier deadline runs first; lower numeric priority wins when two deadlines match. Cancelling the saved event removes it before execution.
Apply it carefully
This clock is a test double, not a production timing implementation. The default scheduler uses a monotonic clock and real sleep. Actions run synchronously, so a slow action delays later events. Priority does not preempt an action that is already running.
The official reference describes the behavior and options. These checks cover the fixture above rather than every input or platform.
Clean up
Remove the saved source, return to the starting directory, then remove the empty practice directory:
rm -- demonstrate-sched.py
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirIf the directory is not empty, inspect its remaining contents rather than deleting unknown files.
Acknowledgements
This post was created with assistance from AI.