前言
書(shū)接上文,本文造第二個(gè)輪子,也是asyncio包里面非常常用的一個(gè)函數(shù)run
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:主機(jī)域名、虛擬主機(jī)、營(yíng)銷軟件、網(wǎng)站建設(shè)、安化網(wǎng)站維護(hù)、網(wǎng)站推廣。
一、知識(shí)準(zhǔn)備
● 相對(duì)于run_until_complete
,改動(dòng)并不大,就是將入口函數(shù)重新封裝了一下,基礎(chǔ)知識(shí)主要還是run_until_complete
的內(nèi)容
● asyncio.run是Python3.7之后新增的入口函數(shù)
二、環(huán)境準(zhǔn)備
組件 | 版本 |
---|---|
python | 3.7.7 |
三、
run
的實(shí)現(xiàn)
先來(lái)看下官方asyncio的使用方法:
|># more main.py
import asyncio
async def hello():
print('enter hello ...')
return 'world'
if __name__ == "__main__":
rst = asyncio.run(hello())
print(rst)
|># python3 main.py
enter hello ...
return world ...
來(lái)看下造的輪子的使用方式:
? more main.py
from wilsonasyncio import run
async def hello():
print('enter hello ...')
return 'return world ...'
if __name__ == "__main__":
ret = run(hello())
print(ret)
? python3 main.py
enter hello ...
return world ...
自己造的輪子也很好的運(yùn)行了,下面我們來(lái)看下輪子的代碼
四、代碼解析
輪子代碼
1)代碼組成
|># tree
.
├── eventloops.py
├── futures.py
├── main.py
├── tasks.py
├── wilsonasyncio.py
文件 | 作用 |
---|---|
eventloops.py | 事件循環(huán) |
futures.py | futures對(duì)象 |
tasks.py | tasks對(duì)象 |
wilsonasyncio.py | 可調(diào)用方法集合 |
main.py | 入口 |
2)代碼概覽:
eventloops.py
類/函數(shù) | 方法 | 對(duì)象 | 作用 | 描述 |
---|---|---|---|---|
Eventloop | 事件循環(huán),一個(gè)線程只有運(yùn)行一個(gè) | |||
__init__ |
初始化兩個(gè)重要對(duì)象 self._ready 與 self._stopping |
|||
self._ready |
所有的待執(zhí)行任務(wù)都是從這個(gè)隊(duì)列取出來(lái),非常重要 | |||
self._stopping |
事件循環(huán)完成的標(biāo)志 | |||
call_soon |
調(diào)用該方法會(huì)立即將任務(wù)添加到待執(zhí)行隊(duì)列 | |||
run_once |
被run_forever 調(diào)用,從self._ready 隊(duì)列里面取出任務(wù)執(zhí)行 |
|||
run_forever |
死循環(huán),若self._stopping 則退出循環(huán) |
|||
run_until_complete |
非常重要的函數(shù),任務(wù)的起點(diǎn)和終點(diǎn)(后面詳細(xì)介紹) | |||
create_task |
將傳入的函數(shù)封裝成task 對(duì)象,這個(gè)操作會(huì)將task.__step 添加到__ready 隊(duì)列 |
|||
Handle |
所有的任務(wù)進(jìn)入待執(zhí)行隊(duì)列(Eventloop.call_soon )之前都會(huì)封裝成Handle對(duì)象 |
|||
__init__ |
初始化兩個(gè)重要對(duì)象 self._callback 與 self._args |
|||
self._callback |
待執(zhí)行函數(shù)主體 | |||
self._args |
待執(zhí)行函數(shù)參數(shù) | |||
_run |
待執(zhí)行函數(shù)執(zhí)行 | |||
get_event_loop |
獲取當(dāng)前線程的事件循環(huán) | |||
_complete_eventloop |
將事件循環(huán)的_stopping 標(biāo)志置位True |
|||
run |
入口函數(shù) | 新增 |
tasks.py
類/函數(shù) | 方法 | 對(duì)象 | 作用 | 描述 |
---|---|---|---|---|
Task | 繼承自Future,主要用于整個(gè)協(xié)程運(yùn)行的周期 | |||
__init__ |
初始化對(duì)象 self._coro ,并且call_soon 將self.__step 加入self._ready 隊(duì)列 |
|||
self._coro |
用戶定義的函數(shù)主體 | |||
__step |
Task類的核心函數(shù) | |||
ensure_future |
如果對(duì)象是一個(gè)Future對(duì)象,就返回,否則就會(huì)調(diào)用create_task 返回,并且加入到_ready 隊(duì)列 |
新增 |
futures.py
類/函數(shù) | 方法 | 對(duì)象 | 作用 | 描述 |
---|---|---|---|---|
Future | 主要負(fù)責(zé)與用戶函數(shù)進(jìn)行交互 | |||
__init__ |
初始化兩個(gè)重要對(duì)象 self._loop 與 self._callbacks |
|||
self._loop |
事件循環(huán) | |||
self._callbacks |
回調(diào)隊(duì)列,任務(wù)暫存隊(duì)列,等待時(shí)機(jī)成熟(狀態(tài)不是PENDING ),就會(huì)進(jìn)入_ready 隊(duì)列 |
|||
add_done_callback |
添加任務(wù)回調(diào)函數(shù),狀態(tài)_PENDING ,就虎進(jìn)入_callbacks 隊(duì)列,否則進(jìn)入_ready 隊(duì)列 |
|||
set_result |
獲取任務(wù)執(zhí)行結(jié)果并存儲(chǔ)至_result ,將狀態(tài)置位_FINISH ,調(diào)用__schedule_callbacks |
|||
__schedule_callbacks |
將回調(diào)函數(shù)放入_ready ,等待執(zhí)行 |
|||
result |
獲取返回值 |
3)執(zhí)行過(guò)程
3.1)入口函數(shù)
main.py
async def hello():
print('enter hello ...')
return 'return world ...'
if __name__ == "__main__":
ret = run(hello())
print(ret)
ret = run(hello())
直接調(diào)用run
,參數(shù)是用戶函數(shù)hello()
,我們看下run的源碼def run(main):
loop = get_event_loop()
return loop.run_until_complete(main)
loop = get_event_loop()
獲取事件循環(huán)return loop.run_until_complete(main)
調(diào)用run_until_complete
3.2)事件循環(huán)啟動(dòng)
def run_until_complete(self, future):
future = tasks.ensure_future(future, loop=self)
future.add_done_callback(_complete_eventloop, future)
self.run_forever()
return future.result()
future = tasks.ensure_future(future, loop=self)
,調(diào)用了tasks.ensure_future
def ensure_future(coro_or_future, *, loop=None):
if isinstance(coro_or_future, Future):
return coro_or_future
else:
return loop.create_task(coro_or_future)
剩下的部分已經(jīng)沒(méi)有什么新鮮的了,和run_until_complete
一樣,我們直接跳過(guò)...
3.7)執(zhí)行結(jié)果
? python3 main.py
enter hello ...
return world ...
五、流程總結(jié)
六、小結(jié)
● run
與run_until_complete
大同小異,只不過(guò)入口函數(shù)做了一些調(diào)整,使得用戶調(diào)用更加的便利
● 本文中的代碼,參考了python 3.7.7中asyncio的源代碼,裁剪而來(lái)
● 本文中代碼:代碼
至此,本文結(jié)束
在下才疏學(xué)淺,有撒湯漏水的,請(qǐng)各位不吝賜教...
更多文章,請(qǐng)關(guān)注我:wilson.chai