最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

python的asyncio模組(三):建立Event Loop和定義協程

XAMPP下载 admin 773浏览 0评论
 在上一篇python的asyncio模組(二):異步程式設計基本概念講解完異步程式設計的基本概念之後,就可以進入正式的主題了:

定義Event Loop
import asyncio
loop = asyncio.get_event_loop() #建立一個Event Loop

# 以下為基本的使用方法
#
# loop.run_until_complete(coroutine)
# coroutine是協程的意思,但其意義以後在介紹,目前只要把他理解成一個任務就行了
# 這個函數顧名思義,就是讓註冊參數裡的任務並執行,等到任務完成就關閉Event Loop
#
# loop.run_forever()
# 這個函數一執行,Event Loop就會永遠執行不會被關閉,除非在程式中出現loop.stop()就停止
#
定義協程(coroutin)
先解釋協程的意義,協程可以看做是”能在中途中斷、中途返回值給其他協程、中途恢復、中途傳入參數的函數”,和一般的函數只能在起始傳入參數,不能中斷,而且最後返回值給父函數之後就結束的概念不一樣。

定義協程很簡單,只要在定義函數時再前面加入”async”這個關鍵字就行了:

# python3.5
# ubuntu 16.04

import asyncio
loop = asyncio.get_event_loop() #建立一個Event Loop

async def example(): # 定義一個協程
print(“Start example coroutin.”)
# do some process…
print(“Finish example coroutin.”)

loop.run_until_complete(example())
# 把example這個coroutin註冊到事件循環裡
# 被註冊進去的事件的定義是loop一啟動就直接觸發的,所以example裡面的任務內容會馬上執行
# output:
# Start example coroutin.
# Finish example coroutin.
但以上的例子無法體會到為何協程可以”中途中斷、中途恢復執行”,下個例子我們可以在協程裡加入asyncio.sleep函數讓他中途暫停執行,並將執行權轉到其他的函數,之後在恢復執行:

# python3.5
# ubuntu 16.04

import asyncio
loop = asyncio.get_event_loop() #建立一個Event Loop

async def example1(): # 定義一個中間會被中斷的協程
print(“Start example1 coroutin.”)
await asyncio.sleep(1) # 中斷協程一秒
print(“Finish example1 coroutin.”)

async def example2(): # 定義一個協程
print(“Start example2 coroutin.”)
# do some process…
print(“Finish example2 coroutin.”)

tasks = [ # 建立一個任務列表
asyncio.ensure_future(example1()),
asyncio.ensure_future(example2()),
]

loop.run_until_complete(asyncio.wait(tasks))
# 把example1, example2這兩個coroutin註冊到事件循環裡
# loop啟動,先執行example1,中途暫停example1之後切換到example2,最後再切回example1
# output:
# Start example1 coroutin.
# Start example2 coroutin.
# Finish example2 coroutin.
# Finish example1 coroutin.
從output資訊可以看出example1是有被中斷執行的但上面的範例多了幾個需要解釋的東西:

asyncio.wait(tasks)
這個函數的實作細節就不多提了,主要意義只是把任務列表都註冊到Event Loop,然後Event Loop必須確定裡面的兩個任務都執行完才能結束Event Loop機制。

asyncio.ensure_future(example1())
這函數把協程封裝成一個task對象,這個對象可以儲存任務執行時的狀態與環境,通常大家會說這對象儲存了任務的”上下文”(context),因為有task對象存在,協程才能順利的暫停與恢復執行,因為暫停時的變數內容都存在task對象裡,就像是遊戲存檔一樣。

其實run_until_complete也是把協程先包裝成task對象後才註冊到Event Loop並執行的。

await asyncio.sleep(1)
asyncio.sleep(1)簡單來說就是啟動一個只有一秒的倒數計時器,比較需要解釋的是await這個關鍵字。
如果沒有加入await的話,那Event Loop只會把計時器放在那邊跑,就不會讓example1暫停了。

如果要讓await這個概念跟上一篇的異步程式概念做一個銜接的話,example1在await之前的部份就像是Callback_B,當遇到await asyncio.sleep(1),Callback_B就會註冊一個”Event_D:Callback_D”進去,而Event_D就是倒數計時器倒數結束,Callback_D就是example1在await之後的部份內容。

QQ截图20181007160756
雖然就我的理解Callback_B和Callback_D其實指的是同樣的協程內容,但是他們task對象儲存的context是不一樣的,也就是他們的存檔點不一樣。

转载请注明:XAMPP中文组官网 » python的asyncio模組(三):建立Event Loop和定義協程

您必须 登录 才能发表评论!