Python的Asyncio模塊提供了管理事件、協(xié)程、任務(wù)和線程的方法,以及編寫(xiě)并發(fā)代碼的原語(yǔ)。此模塊的主要組件和概念包括:
- 事件循環(huán) : 在Asyncio模塊中,每一個(gè)進(jìn)程都有一個(gè)事件循環(huán)。
- 協(xié)程 : 這是子程序的泛化概念。協(xié)程可以在執(zhí)行期間暫停,這樣就可以等待外部的處理(例如IO)完成之后,從之前暫停的地方恢復(fù)執(zhí)行。
- Futures : 定義了
Future
對(duì)象,和concurrent.futures
模塊一樣,表示尚未完成的計(jì)算。 - Tasks : 這是Asyncio的子類(lèi),用于封裝和管理并行模式下的協(xié)程。
本節(jié)中重點(diǎn)討論事件,事實(shí)上,異步編程的上下文中,事件無(wú)比重要。因?yàn)槭录谋举|(zhì)就是異步。
1. 什么是事件循環(huán)
在計(jì)算系統(tǒng)中,可以產(chǎn)生事件的實(shí)體叫做事件源,能處理事件的實(shí)體叫做事件處理者。
此外,還有一些第三方實(shí)體叫做事件循環(huán)。它的作用是管理所有的事件,在整個(gè)程序運(yùn)行過(guò)程中不斷循環(huán)執(zhí)行,追蹤事件發(fā)生的順序?qū)⑺鼈兎诺疥?duì)列中,當(dāng)主線程空閑的時(shí)候,調(diào)用相應(yīng)的事件處理者處理事件。
最后,我們可以通過(guò)下面的偽代碼來(lái)理解事件循環(huán):
while(1) {
events = getEvents();
for (e in events)
processEvent(e);
}
所有的事件都在 ** while
**循環(huán)中捕捉,然后經(jīng)過(guò)事件處理者處理。事件處理的部分是系統(tǒng)唯一活躍的部分,當(dāng)一個(gè)事件處理完成,流程繼續(xù)處理下一個(gè)事件。
2. 準(zhǔn)備工作
Asyncio提供了以下方法來(lái)管理事件循環(huán):
- **
loop = get_event_loop()
** : 得到當(dāng)前上下文的事件循環(huán)。 - **
loop.call_later(time_delay, callback, arg)
** : 延后 time_delay 秒再執(zhí)行 callback 方法。 - **
loop.call_soon(callback, argument)
** : 盡可能快調(diào)用 callback, call_soon() 函數(shù)結(jié)束,主線程回到事件循環(huán)之后就會(huì)馬上調(diào)用 callback 。 - **
loop.time()
** : 以float類(lèi)型返回當(dāng)前事件循環(huán)的內(nèi)部時(shí)間。 - **
asyncio.set_event_loop()
** : 為當(dāng)前上下文設(shè)置事件循環(huán)。 - **
asyncio.new_event_loop()
** : 根據(jù)此策略創(chuàng)建一個(gè)新的事件循環(huán)并返回。 - **
loop.run_forever()
**: 在調(diào)用 stop() 之前將一直運(yùn)行。
3. 如何做…
下面的代碼中,我們將展示如何使用Asyncio庫(kù)提供的事件循環(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()
運(yùn)行結(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
在這個(gè)例子中,我們定義了三個(gè)異步的任務(wù),相繼執(zhí)行,入下圖所示的順序。
首先,我們要得到這個(gè)事件循環(huán):
loop = asyncio.get_event_loop()
然后我們通過(guò)** call_soon
**方法調(diào)用了 ** function_1()
** 函數(shù)。
end_loop = loop.time() + 9.0
loop.call_soon(function_1, end_loop, loop)
讓我們來(lái)看一下 ** 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()
這個(gè)函數(shù)通過(guò)以下參數(shù)定義了應(yīng)用的異步行為:
- **
end_time
** : 定義了 function_1() 可以運(yùn)行的最長(zhǎng)時(shí)間,并通過(guò) call_later 方法傳入到 function_2() 中作為參數(shù) - **
loop
** : 之前通過(guò) get_event_loop() 方法得到的事件循環(huán)。
** function_1()
** 的任務(wù)非常簡(jiǎn)單,只是打印出函數(shù)名字。當(dāng)然,里面也可以寫(xiě)非常復(fù)雜的操作。
print("function_1 called")
任務(wù)執(zhí)行結(jié)束之后,它將會(huì)比較 ** loop.time()
** **+1s 和設(shè)定的運(yùn)行時(shí)間,如果沒(méi)有超過(guò),使用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()
**** 的作用類(lèi)似。如果運(yùn)行的時(shí)間超過(guò)了設(shè)定,事件循環(huán)終止。
loop.run_forever()
loop.close()
-
模塊
+關(guān)注
關(guān)注
7文章
2671瀏覽量
47341 -
程序
+關(guān)注
關(guān)注
116文章
3777瀏覽量
80853 -
代碼
+關(guān)注
關(guān)注
30文章
4748瀏覽量
68357 -
python
+關(guān)注
關(guān)注
56文章
4782瀏覽量
84456
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論