期程
****

*期程* 对象用来链接  **底层回调式代码** 和高层异步/等待式代码。


期程函数
========

asyncio.isfuture(obj)

   如果 *obj* 为下面任意对象，返回 "True"：

   * an instance of "asyncio.Future",

   * an instance of "asyncio.Task",

   * 带有  "_asyncio_future_blocking" 属性的类似期程的对象。

   3.5 新版功能.

asyncio.ensure_future(obj, *, loop=None)

   返回：

   * *obj* 参数会是保持原样，如果 *obj* 是 "Future"、 "Task" 或 类似
     期 程的对象(  "isfuture()"  用于测试)

   * 封装着 *obj* 的 "Task" 对象 ，如果 *obj* 是一个协程(
     "iscoroutine()" 用于测试)

   * 等待 *obj* 的 "Task" 对象，如果 *obj* 是一个可等待对象(
     "inspect.isawaitable()" 用于测试)

   如果 *obj* 不是上述对象会引发一个 "TypeError" 异常。

   重要: 查看 "create_task()" 函数，它是创建新任务的首选途径。

   在 3.5.1 版更改: 这个函数接受任意 *awaitable* 对象。

asyncio.wrap_future(future, *, loop=None)

   将一个 "concurrent.futures.Future" 对象封装到 "asyncio.Future" 对象
   中。


期程对象
========

class asyncio.Future(*, loop=None)

   一个期程代表一个异步运算的最终结果。线程不安全。

   期程是一个 *awaitable* 对象。协程可以等待期程对象直到它们有结果或异
   常集合或被取消。

   通常期程用于支持底层回调式代码(例如在协议实现中使用asyncio
   transports) 与高层异步/等待式代码交互。

   经验告诉我们永远不要面向用户的接口暴露期程对象，同时建议使用
   "loop.create_future()" 来创建期对象。这种方法可以让期程对象使用其它
   的事件循环实现，它可以注入自己的优化实现。

   在 3.7 版更改: 加入对 "contextvars" 模块的支持。

   result()

      返回期程结果。

      如果期程状态为 *完成* ，并由 "set_result()" 方法设置一个结果，则
      返回这个结果。

      如果期程状态为 *完成* ，并由  "set_exception()" 方法设置一个异常
      ，那么这个方法会引发异常。

      如果期程已 *取消*，方法会引发一个 "CancelledError" 异常。

      如果期程的结果还不可用，此方法会引发一个 "InvalidStateError" 异
      常。

   set_result(result)

      将期程标记为 *完成* 并设置结果。

      如果期程已经 *完成*  则引发一个 "InvalidStateError" 错误。

   set_exception(exception)

      将期程标记为 *完成* 并设置一个异常。

      如果期程已经 *完成*  则引发一个 "InvalidStateError" 错误。

   done()

      如果期程为已 *完成* 返回 "True" 。

      如果期程为 *取消* 或调用 "set_result()" 设置了结果或调用
      "set_exception()" 设置了异常，那么它就是 *完成* 。

   cancelled()

      如果期程已 *取消* 返回 "True"

      这个方法通常在设置结果或异常前用来检查期程是否已 *取消* 。

         if not fut.cancelled():
             fut.set_result(42)

   add_done_callback(callback, *, context=None)

      添加一个在期程 *完成* 时运行的回调函数。

      调用 *callback* 时，期程对象是它的唯一参数。

      调用这个方法时期程已经 *完成* , 回调函数已被 "loop.call_soon()"
      调度。

      可选键值类的参数 *context* 允许 *callback* 运行在一个指定的自定
      义 "contextvars.Context" 对象中。如果没有提供 *context* ，则使用
      当前上下文。

      可以用 "functools.partial()" 给回调函数传递参数，例如:

         # Call 'print("Future:", fut)' when "fut" is done.
         fut.add_done_callback(
             functools.partial(print, "Future:"))

      在 3.7 版更改: 加入键值类形参  *context*。请参阅 **PEP 567** 查
      看更多细节。

   remove_done_callback(callback)

      从回调列表中移除 *callback* 。

      返回被移除的回调函数的数量，通常为1，除非一个回调函数被添加多次
      。

   cancel()

      取消期程并调度回调函数。

      如果期程已经 *完成* 或 *取消* ，返回 "False" 。否则将期程状态改
      为 *取消* 并在调度回调函数后返回 "True" 。

   exception()

      返回期程已设置的异常。

      只有期程在 *完成* 时才返回异常(或者 "None" ，如果没有设置异常 )
      。

      如果期程已 *取消*，方法会引发一个 "CancelledError" 异常。

      如果期程还没 *完成* ，这个方法会引发一个 "InvalidStateError" 异
      常。

   get_loop()

      返回期程对象已绑定的事件循环。

      3.7 新版功能.

这个例子创建一个期程对象，创建和调度一个异步作业去设置期程结果，然后等
待期程的结果:

   async def set_after(fut, delay, value):
       # Sleep for *delay* seconds.
       await asyncio.sleep(delay)

       # Set *value* as a result of *fut* Future.
       fut.set_result(value)

   async def main():
       # Get the current event loop.
       loop = asyncio.get_running_loop()

       # Create a new Future object.
       fut = loop.create_future()

       # Run "set_after()" coroutine in a parallel Task.
       # We are using the low-level "loop.create_task()" API here because
       # we already have a reference to the event loop at hand.
       # Otherwise we could have just used "asyncio.create_task()".
       loop.create_task(
           set_after(fut, 1, '... world'))

       print('hello ...')

       # Wait until *fut* has a result (1 second) and print it.
       print(await fut)

   asyncio.run(main())

重要: 该期程对象是为了模仿 "concurrent.futures.Future" 。主要差异包
  含：

  * "concurrent.futures.Future"  实例不能像asyncio期程那样等待。

  * "asyncio.Future.result()" 和 "asyncio.Future.exception()" 不接受
    *timeout* 参数。

  * 期程没有 *完成* 时 "asyncio.Future.result()" 和
    "asyncio.Future.exception()" 引发 "InvalidStateError" 引发一个异常
    。

  * 使用 "asyncio.Future.add_done_callback()" 注册的回调函数不会立即
    调 用，而是被 "loop.call_soon()" 调度。

  * asyncio期程不能兼容  "concurrent.futures.wait()" 和
    "concurrent.futures.as_completed()" 函数。
