"sched" --- 事件调度器
**********************

**源码：** Lib/sched.py

======================================================================

"sched" 模块定义了一个实现通用事件调度器的类：

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

   "scheduler" 类定义了一个调度事件的通用接口。它需要两个函数来实际处
   理“外部世界” —— *timefunc* 应当不带参数地调用，并返回一个数字（“时
   间”，可以为任意单位）。 *delayfunc* 函数应当带一个参数调用，与
   *timefunc* 的输出相兼容，并且应当延迟其所指定的时间单位。每个事件运
   行后还将调用 *delayfunc* 并传入参数 "0" 以允许其他线程有机会在多线
   程应用中运行。

   在 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',))
   ...     # 虽然具有更高的优先级，'keyword' 将在 'positional' 之后运行，因为 enter() 是相对的
   ...     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* 函
   数）下一个事件，然后执行它，依此类推直到没有更多的计划事件。

   If *blocking* is false, immediately executes all events in the
   queue which have a time value less than or equal to the current
   *timefunc* value (if any) and returns the difference between the
   current *timefunc* value and the time value of the next scheduled
   event in the scheduler's event queue.  If the queue is empty,
   returns "None".

   *action* 或 *delayfunc* 都可以引发异常。在任何一种情况下，调度程序
   都将保持一致状态并传播异常。如果 *action* 引发异常，则在将来调用
   "run()" 时不会尝试该事件。

   如果一系列事件的运行时间大于下一个事件发生前的可用时间，那么调度程
   序只会保持落后。没有事件会被丢弃；调用代码负责取消不再相关的事件。

   在 3.3 版本发生变更: 添加了 *blocking* 形参。

scheduler.queue

   只读属性，按照计划运行的顺序返回即将发生的事件列表。每个事件都显示
   为 *named tuple* ，包含以下字段：time、priority、action、argument、
   kwargs。
