天天看點

從頭造輪子:python3 asyncio 之 run(2)

書接上文,本文造第二個輪子,也是asyncio包裡面非常常用的一個函數<code>run</code>

● 相對于<code>run_until_complete</code>,改動并不大,就是将入口函數重新封裝了一下,基礎知識主要還是<code>run_until_complete</code>的内容

● asyncio.run是Python3.7之後新增的入口函數

元件

版本

python

3.7.7

先來看下官方asyncio的使用方法:

來看下造的輪子的使用方式:

自己造的輪子也很好的運作了,下面我們來看下輪子的代碼

輪子代碼

1)代碼組成

檔案

作用

eventloops.py

事件循環

futures.py

futures對象

tasks.py

tasks對象

wilsonasyncio.py

可調用方法集合

main.py

入口

2)代碼概覽:

類/函數

方法

對象

描述

Eventloop

事件循環,一個線程隻有運作一個

<code>__init__</code>

初始化兩個重要對象 <code>self._ready</code> 與 <code>self._stopping</code>

<code>self._ready</code>

所有的待執行任務都是從這個隊列取出來,非常重要

<code>self._stopping</code>

事件循環完成的标志

<code>call_soon</code>

調用該方法會立即将任務添加到待執行隊列

<code>run_once</code>

被<code>run_forever</code>調用,從<code>self._ready</code>隊列裡面取出任務執行

<code>run_forever</code>

死循環,若<code>self._stopping</code>則退出循環

<code>run_until_complete</code>

非常重要的函數,任務的起點和終點(後面詳細介紹)

<code>create_task</code>

将傳入的函數封裝成<code>task</code>對象,這個操作會将<code>task.__step</code>添加到<code>__ready</code>隊列

<code>Handle</code>

所有的任務進入待執行隊列(<code>Eventloop.call_soon</code>)之前都會封裝成Handle對象

初始化兩個重要對象 <code>self._callback</code> 與 <code>self._args</code>

<code>self._callback</code>

待執行函數主體

<code>self._args</code>

待執行函數參數

<code>_run</code>

待執行函數執行

<code>get_event_loop</code>

擷取目前線程的事件循環

<code>_complete_eventloop</code>

将事件循環的<code>_stopping</code>标志置位True

<code>run</code>

入口函數

新增

Task

繼承自Future,主要用于整個協程運作的周期

初始化對象 <code>self._coro</code> ,并且<code>call_soon</code>将<code>self.__step</code>加入<code>self._ready</code>隊列

<code>self._coro</code>

使用者定義的函數主體

<code>__step</code>

Task類的核心函數

<code>ensure_future</code>

如果對象是一個Future對象,就傳回,否則就會調用<code>create_task</code>傳回,并且加入到<code>_ready</code>隊列

Future

主要負責與使用者函數進行互動

初始化兩個重要對象 <code>self._loop</code> 與 <code>self._callbacks</code>

<code>self._loop</code>

<code>self._callbacks</code>

回調隊列,任務暫存隊列,等待時機成熟(狀态不是<code>PENDING</code>),就會進入<code>_ready</code>隊列

<code>add_done_callback</code>

添加任務回調函數,狀态<code>_PENDING</code>,就虎進入<code>_callbacks</code>隊列,否則進入<code>_ready</code>隊列

<code>set_result</code>

擷取任務執行結果并存儲至<code>_result</code>,将狀态置位<code>_FINISH</code>,調用<code>__schedule_callbacks</code>

<code>__schedule_callbacks</code>

将回調函數放入<code>_ready</code>,等待執行

<code>result</code>

擷取傳回值

3)執行過程

3.1)入口函數

<code>ret = run(hello())</code>直接調用<code>run</code>,參數是使用者函數<code>hello()</code>,我們看下run的源碼

<code>loop = get_event_loop()</code>擷取事件循環

<code>return loop.run_until_complete(main)</code>調用<code>run_until_complete</code>

3.2)事件循環啟動

與之前略有不同,<code>future = tasks.ensure_future(future, loop=self)</code>,調用了<code>tasks.ensure_future</code>

如果傳入的對象是一個普通函數,那就封裝成一個task;如果已經是一個future對象,那就直接傳回。這一步的目的主要是確定傳入的對象,是一個Future類型

剩下的部分已經沒有什麼新鮮的了,和<code>run_until_complete</code>一樣,我們直接跳過...

3.7)執行結果

從頭造輪子:python3 asyncio 之 run(2)

● <code>run</code>與<code>run_until_complete</code>大同小異,隻不過入口函數做了一些調整,使得使用者調用更加的便利

● 本文中的代碼,參考了python 3.7.7中asyncio的源代碼,裁剪而來

● 本文中代碼:代碼

至此,本文結束

在下才疏學淺,有撒湯漏水的,請各位不吝賜教...

更多文章,請關注我:wilson.chai

本文來自部落格園,作者:wilson排球,轉載請注明原文連結:https://www.cnblogs.com/MrVolleyball/p/15739907.html

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須在文章頁面給出原文連接配接,否則保留追究法律責任的權利。