深刻Asyncio(六)Tasks and Futures

Tasks and Futures

大多数的工做只涉及到Task、create_task()方法,就像前面代码同样,Future是Task的父类,提供与loop交互的全部功能。bash

Future对象表示某个活动的将来完成状态,由loop管理,Task与之彻底相同,但其活动特指coroutine。Future表示与loop交互的状态,Future对象描述的是完成状态的切换,其实例建立时状态是“还没有完成”,而后在稍后的一段时间后,实例状态为完成,Future的实例有一个done()方法用于检查状态。框架

>>> from asyncio import Future
>>> f = Future()
>>> f.done()
False

Future实例可能:async

  1. 有一个结果集(set_result(value)result());
  2. 可用cancel()取消(经过cancelled()检查);
  3. 拥有回调函数,并在完成时执行。

即便Task更广泛,但Future仍然没法避免,例如在executor中运行一个函数会返回一个Future对象而非Task。函数

>>> async def main(f: asyncio.Future):  # 1
...     await asyncio.sleep(1)
...     f.set_result('I have finished')    # 2
>>> loop = asyncio.get_event_loop()
>>> fut = asyncio.Future()  # 3
>>> print(fut.done())   # 4
False
>>> loop.create_task(main(fut))    # 5
<Task pending coro=<main() running at <stdin>:1>>
>>> loop.run_until_complete(fut)    # 6
'I have finished'
>>> print(fut.done())
True
>>> print(fut.result())    # 7
I have finished
  1. 建立一个简单的主函数;
  2. 为Future对象设置结果;
  3. 手动建立一个Future对象,该对象默认绑定在当前loop上,不能也不会属于任何coroutine;
  4. 在作任何事以前,先确认Future对象完成状态;
  5. 调度主程序,并将Future对象传递进去,主程序只是sleep,而后切换到Future对象,而且此时loop还未启动;
  6. 这里与之前不一样的是,用Future对象而不是Task对象,如今loop开始运行;
  7. Future在设置结果时完成,而后能够访问结果。

绝大多数代码都不会像上面同样直接用Future对象,这里仅做学习用。oop

create_task仍是ensure_future

后者很容易形成误解,从官方的函数docstring看:学习

asyncio.ensure_future(coro_or_future, *, loop=None)
Schedule the execution of a coroutine object: wrap it in a future. Return a Task object.
If the argument is a Future, it is returned directly.code

清楚的解释一下:
1. 若是传入一个coroutine,它将返回一个Task(coroutine将会在loop中调度),这与直接调用create_task()没区别;
2. 若是传入一个Future,直接返回,彻底没有改变地!对象

import asyncio

async def f():  # 1
    pass

coro = f()  # 2
loop = asyncio.get_event_loop()    # 3

task = loop.create_task(coro)   # 4
assert isinstance(task, asyncio.Task)   # 5

new_task = asyncio.ensure_future(coro)  # 6
assert isinstance(new_task, asyncio.Task)

mystery_meat = asyncio.ensure_future(task)  # 7
assert mystery_meat is task    # 8
  1. 一个coroutine function;
  2. 得到coroutine;
  3. 得到loop;
  4. 经过create_task调度coroutine;
  5. 类型检查;
  6. 与create_task相同;
  7. Task是Future的子类,这里直接传入一个已经建立好的Task实例;
  8. 结果是True,彻底没区别。

实际上,ensure_future()是提供给框架开发者处理两种参数用的。ci

在3.7中,asyncio提供了asyncio.create_task(coro)方法来为运行中的loop添加task,ensure_future()能够失业了。开发

相关文章
相关标签/搜索