title: Usage of builtin sched module's non-blocking scheduler.run() method?
body: <p>I'd like to understand how to use the optional parameter <code>blocking</code> in the method <a href="https://docs.python.org/3/library/sched.html#sched.scheduler.run" rel="noreferrer"><code>scheduler.run(blocking=True)</code></a>. Any practical/real-world example would be very helpful.</p>
  
  <p>Based on the research I've done so far, the intention of the <code>blocking</code> optional argument is for non-blocking or async applications<sup>[1]</sup><sup>[2]</sup>. Below is the main run loop of the schduler (from the python 3.6 library <a href="https://github.com/python/cpython/blob/master/Lib/sched.py#L138-L155" rel="noreferrer"><code>sched.py</code></a>). Following through the code, I notice that whenever <code>blocking</code> is set to <code>False</code>, immediately returns the time difference between target time and current time, unless the target time had passed, in which case the action would be executed.</p>
  
  <pre><code>while True:
      with lock:
          if not q:
              break
          time, priority, action, argument, kwargs = q[0]
          now = timefunc()
          if time &gt; now:
              delay = True
          else:
              delay = False
              pop(q)
      if delay:
          if not blocking:
              return time - now
          delayfunc(time - now)
      else:
          action(*argument, **kwargs)
          delayfunc(0)   # Let other threads run
  </code></pre>
  
  <p>Seems to me the non-blocking design requires me to keep running the scheduler until the queue is clean. Thus, I'm thinking about maintaining a task queue myself and keep pushing the <code>scheduler.run</code> task into the queue (like the code below.) Is this a  desirable design? What is the proper way of using the non-blocking scheduler?</p>
  
  <pre><code>def action():
      print('action at: ', datetime.now())
  
  if __name__ == '__main__':
      s = sched.scheduler(time.time)
      target_time = datetime.now() + timedelta(seconds=5)
      s.enterabs(target_time.timestamp(), 1, action)
      run = functools.partial(s.run, blocking=False)
      taskq = deque()
      taskq.append(run)
      while taskq:
          task = taskq.popleft()
          result = task()
          print(result)
          if result:
              taskq.append(run)
              time.sleep(1)
  
      print('end tasks')
  </code></pre>
  
  <p>[1] <a href="https://docs.python.org/release/3.3.0/whatsnew/3.3.html#sched" rel="noreferrer">What’s New In Python 3.3</a></p>
  
  <p>[2] <a href="http://bugs.python.org/issue13449" rel="noreferrer">Issue13449: sched - provide an "async" argument for run() method</a></p>