Python 想了解EventLoop?這篇文章就夠了
本文轉(zhuǎn)自: python-parallel-programming-cookbook-cn.
Python的Asyncio模塊提供了管理事件、協(xié)程、任務(wù)和線程的方法,以及編寫并發(fā)代碼的原語。此模塊的主要組件和概念包括:
事件循環(huán): 在Asyncio模塊中,每一個進程都有一個事件循環(huán)。
協(xié)程: 這是子程序的泛化概念。協(xié)程可以在執(zhí)行期間暫停,這樣就可以等待外部的處理(例如IO)完成之后,從之前暫停的地方恢復(fù)執(zhí)行。
Futures: 定義了
Future對象,和concurrent.futures模塊一樣,表示尚未完成的計算。Tasks: 這是Asyncio的子類,用于封裝和管理并行模式下的協(xié)程。
本節(jié)中重點討論事件,事實上,異步編程的上下文中,事件無比重要。因為事件的本質(zhì)就是異步。
1. 什么是事件循環(huán)
在計算系統(tǒng)中,可以產(chǎn)生事件的實體叫做事件源,能處理事件的實體叫做事件處理者。
此外,還有一些第三方實體叫做事件循環(huán)。它的作用是管理所有的事件,在整個程序運行過程中不斷循環(huán)執(zhí)行,追蹤事件發(fā)生的順序?qū)⑺鼈兎诺疥犃兄校?dāng)主線程空閑的時候,調(diào)用相應(yīng)的事件處理者處理事件。
最后,我們可以通過下面的偽代碼來理解事件循環(huán):
while(1) {
events = getEvents();
for (e in events)
processEvent(e);
}所有的事件都在 while 循環(huán)中捕捉,然后經(jīng)過事件處理者處理。事件處理的部分是系統(tǒng)唯一活躍的部分,當(dāng)一個事件處理完成,流程繼續(xù)處理下一個事件。
2. 準(zhǔn)備工作
Asyncio提供了以下方法來管理事件循環(huán):
1. loop = get_event_loop() : 得到當(dāng)前上下文的事件循環(huán)。
2. loop.call_later(time_delay, callback, arg) : 延后 time_delay 秒再執(zhí)行 callback 方法。
3. loop.call_soon(callback, argument) : 盡可能快調(diào)用 callback, call_soon() 函數(shù)結(jié)束,主線程回到事件循環(huán)之后就會馬上調(diào)用 callback 。
4. loop.time() : 以float類型返回當(dāng)前事件循環(huán)的內(nèi)部時間。
5. asyncio.set_event_loop() : 為當(dāng)前上下文設(shè)置事件循環(huán)。
6. asyncio.new_event_loop() : 根據(jù)此策略創(chuàng)建一個新的事件循環(huán)并返回。
7. loop.run_forever() : 在調(diào)用 stop() 之前將一直運行。
3. 如何做…
下面的代碼中,我們將展示如何使用Asyncio庫提供的事件循環(huán)創(chuàng)建異步模式的應(yīng)用。
import asyncio
import datetime
import time
def function_1(end_time, loop):
print("function_1 called")
if (loop.time() + 1.0) < end_time:
loop.call_later(1, function_2, end_time, loop)
else:
loop.stop()
def function_2(end_time, loop):
print("function_2 called ")
if (loop.time() + 1.0) < end_time:
loop.call_later(1, function_3, end_time, loop)
else:
loop.stop()
def function_3(end_time, loop):
print("function_3 called")
if (loop.time() + 1.0) < end_time:
loop.call_later(1, function_1, end_time, loop)
else:
loop.stop()
def function_4(end_time, loop):
print("function_5 called")
if (loop.time() + 1.0) < end_time:
loop.call_later(1, function_4, end_time, loop)
else:
loop.stop()
loop = asyncio.get_event_loop()
end_loop = loop.time() + 9.0
loop.call_soon(function_1, end_loop, loop)
# loop.call_soon(function_4, end_loop, loop)
loop.run_forever()
loop.close()運行結(jié)果如下:
python3 event.py
function_1 called
function_2 called
function_3 called
function_1 called
function_2 called
function_3 called
function_1 called
function_2 called
function_3 called在這個例子中,我們定義了三個異步的任務(wù),相繼執(zhí)行,入下圖所示的順序。

首先,我們要得到這個事件循環(huán):
loop = asyncio.get_event_loop()然后我們通過 call_soon 方法調(diào)用了 function_1() 函數(shù)。
end_loop = loop.time() + 9.0
loop.call_soon(function_1, end_loop, loop)讓我們來看一下 function_1() 的定義:
def function_1(end_time, loop):
print("function_1 called")
if (loop.time() + 1.0) < end_time:
loop.call_later(1, function_2, end_time, loop)
else:
loop.stop()這個函數(shù)通過以下參數(shù)定義了應(yīng)用的異步行為:
1. end_time : 定義了 function_1() 可以運行的最長時間,并通過 call_later 方法傳入到 function_2() 中作為參數(shù)
2. loop : 之前通過 get_event_loop() 方法得到的事件循環(huán)。
function_1() 的任務(wù)非常簡單,只是打印出函數(shù)名字。當(dāng)然,里面也可以寫非常復(fù)雜的操作。
print("function_1 called")任務(wù)執(zhí)行結(jié)束之后,它將會比較 loop.time() +1s 和設(shè)定的運行時間,如果沒有超過,使用 call_later 在1秒之后執(zhí)行 function_2()
if (loop.time() + 1.0) < end_time:
loop.call_later(1, function_2, end_time, loop)
else:
loop.stop()其中function_2() 和 function_3() 的作用類似。如果運行的時間超過了設(shè)定,事件循環(huán)終止。
loop.run_forever()
loop.close()我們的文章到此就結(jié)束啦,如果你喜歡今天的Python 實戰(zhàn)教程,請持續(xù)關(guān)注Python實用寶典。
有任何問題,可以在公眾號后臺回復(fù):加群,回答相應(yīng)紅字驗證信息,進入互助群詢問。
原創(chuàng)不易,希望你能在下面點個贊和在看支持我繼續(xù)創(chuàng)作,謝謝!
點擊下方閱讀原文可獲得更好的閱讀體驗
Python實用寶典 (pythondict.com)
不只是一個寶典
歡迎關(guān)注公眾號:Python實用寶典
