深刻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()能夠失業了。開發

相關文章
相關標籤/搜索