# `sched` --- 事件排程器

原始碼：Lib/sched.py

`sched` 模組定義了一個有實作通用事件排程器的類別：

class sched.scheduler(timefunc=time.monotonic, delayfunc=time.sleep)

  `scheduler` 類別定義了事件排程的泛用介面。它需要兩個函式來和「外部世界」作用 —— timefunc 應不帶引數地被呼叫，並回傳一個數字（為「時間」，可為任何單位）。delayfunc 函式應以一個引數呼叫，並與 timefunc 的輸出相容，且應延遲其指定的時間單位。每個事件運行後，也會以引數 `0` 呼叫 delayfunc，來使得其他執行緒有機會在多執行緒應用程式中運行。

  在 3.3 版的變更: timefunc 和 delayfunc 參數是可選的。

  在 3.3 版的變更: `scheduler` 類別可以安全地在多執行緒環境中使用。

範例：

    >>> import sched, time
    >>> s = sched.scheduler(time.time, time.sleep)
    >>> def print_time(a='default'):
    ...     print("From print_time", time.time(), a)
    ...
    >>> def print_some_times():
    ...     print(time.time())
    ...     s.enter(10, 1, print_time)
    ...     s.enter(5, 2, print_time, argument=('positional',))
    ...     # 儘管優先順序較高，但由於 enter() 是相對的，'keyword' 在 'positional' 之後運行
    ...     s.enter(5, 1, print_time, kwargs={'a': 'keyword'})
    ...     s.enterabs(1_650_000_000, 10, print_time, argument=("first enterabs",))
    ...     s.enterabs(1_650_000_000, 5, print_time, argument=("second enterabs",))
    ...     s.run()
    ...     print(time.time())
    ...
    >>> print_some_times()
    1652342830.3640375
    From print_time 1652342830.3642538 second enterabs
    From print_time 1652342830.3643398 first enterabs
    From print_time 1652342835.3694863 positional
    From print_time 1652342835.3696074 keyword
    From print_time 1652342840.369612 default
    1652342840.3697174

## 排程器物件

`scheduler` 實例具有以下方法和屬性：

scheduler.enterabs(time, priority, action, argument=(), kwargs={})

  為一個新事件排程。time 引數應該是與傳遞給建構函式的 timefunc 函式回傳值相容的數字型別。安排在相同 time 的事件將按照其 priority 的順序執行。數字越小代表優先順序越高。

  執行事件意味著執行 `action(*argument, **kwargs)`。argument 是一個包含 action 之位置引數的序列。kwargs 是一個字典，帶有 action 的關鍵字引數。

  回傳值是一個事件，可用於後續取消該事件（請見 `cancel()`）。

  在 3.3 版的變更: argument 參數是可選的。

  在 3.3 版的變更: 新增 kwargs 參數。

scheduler.enter(delay, priority, action, argument=(), kwargs={})

  為一個排程事件延期 delay 個時間單位。除了相對時間之外，其他引數、效果和回傳值皆與 `enterabs()` 的相同。

  在 3.3 版的變更: argument 參數是可選的。

  在 3.3 版的變更: 新增 kwargs 參數。

scheduler.cancel(event)

  從佇列中刪除該事件。如果 event 不是目前佇列中的事件，此方法將引發 `ValueError`。

scheduler.empty()

  如果事件佇列為空，則回傳 `True`。

scheduler.run(blocking=True)

  運行所有已排程的事件。此方法將會等待（使用傳遞給建構函式的 delayfunc 函式）下一個事件，然後執行它，並依此類推，直到不再有排程好的事件。

  如果 blocking 為 false，則執行最快到期的已排程事件（如存在），然後回傳排程器中下一個排程呼叫（如存在）的截止時間。

  action 或 delayfunc 都可能引發例外。無論哪種情況，排程器都將保持一致的狀態並傳遞例外。如果是由 action 引發例外，則後續呼叫 `run()` 時將不會嘗試運行該事件。

  如果一系列事件的運行時長比執行下一個事件前的可用時長 (available time) 更長，那麼排程器就單純會落後。不會有事件被丟棄；呼叫程式碼也要負責取消不再相關的事件。

  在 3.3 版的變更: 新增 blocking 參數。

scheduler.queue

  會按事件運行順序回傳即將發生的事件串列的唯讀屬性。每個事件都以附名元組 (named tuple) 表示，並包含以下欄位：時間、優先順序、動作 (action)、引數、kwargs。