API reference: Scheduler

class schedium.scheduler.Scheduler[source][source]

Bases: object

Simple in-process scheduler.

This scheduler is intentionally minimal:

  • Jobs run inline (no threads/processes by default).

  • User is responsible for calling run_pending() periodically.

  • Deduplication is handled per-job: if you call run_pending() multiple times within the same trigger “token” (e.g., the same minute bucket), the job runs only once.

Notes

  • run_pending() returns a list aligned with jobs. For jobs that

    are not due, the entry is the sentinel JobDidNotRun.

  • Many triggers match only at specific boundaries (minute/hour/day). In

    production, call run_pending() on a short interval (e.g., once per second) so you don’t skip over a matching boundary.

Examples

Run something every 5 minutes

>>> from datetime import datetime
>>> from schedium import JobDidNotRun, Every, Job, Scheduler
>>> sched = Scheduler()
>>> def tick():
...     print("tick")
>>> sched.append(Job(tick, Every(unit="minute", interval=5)))
>>> results = sched.run_pending(now=datetime(2026, 2, 4, 10, 1, 0))
>>> results[0] is JobDidNotRun
True
>>> results = sched.run_pending(now=datetime(2026, 2, 4, 10, 5, 0))
tick
>>> results
[None]

Deduplication when called repeatedly at the same timestamp

>>> results = sched.run_pending(now=datetime(2026, 2, 4, 10, 5, 0))  # same minute bucket
>>> results[0] is JobDidNotRun
True

Combine triggers (weekday at 08:00)

>>> from schedium import On
>>> weekday_8am = (
...     Every(unit="day", interval=1)
...     & On(unit="weekdays")
...     & On(unit="hour_of_day", value=8)
... )
>>> sched = Scheduler()
>>> def weekday_job():
...     print("weekday job")
>>> sched.append(Job(weekday_job, weekday_8am))
>>> results = sched.run_pending(now=datetime(2026, 2, 2, 8, 0, 0))  # Monday
weekday job
>>> results
[None]

Inspect the next run time across all jobs

>>> sched.time_of_next_run(after=datetime(2026, 2, 2, 8, 0, 1))
datetime.datetime(2026, 2, 3, 8, 0)
append(job)[source][source]

Append an already-constructed job.

Parameters:
jobJob

The job to append. The job’s trigger is used to determine when it runs.

Parameters:

job (Job)

Return type:

None

run_pending(now=None)[source][source]

Run all jobs that are due at now.

Parameters:
nowdatetime, optional

If provided, uses this timestamp to evaluate triggers. If omitted, uses the current system time.

Returns:
list[object]

The list of return values from each job. If a job is not due, its return value is JobDidNotRun.

If a job runs and returns CancelJob, the job is removed from the scheduler.

Parameters:

now (datetime | None)

Return type:

list[object]

time_of_next_run(after=None, *, max_iterations=100000)[source][source]

Return the earliest next run time across all jobs.

This asks each job’s trigger for its next run time and returns the minimum. Triggers that cannot compute a next time are ignored.

Parameters:
afterdatetime, optional

Lower bound (inclusive) for the computed next run time. If omitted, uses the current system time.

max_iterationsint, default 100_000

Safety cap used by some triggers/combinators that scan forward.

Parameters:
  • after (datetime | None)

  • max_iterations (int)

Return type:

datetime | None