在本教程中,我們將學習事件驅動編程以及可以用來進行 Python 事件驅動編程的 Python 模塊(Asyncio)。
事件驅動編程
最終,程序的流程依賴於事件,而專註於事件的編程稱為事件驅動編程。我們只處理並行或順序模型,但是現在我們將討論異步模型。遵循事件驅動編程概念的編程模型稱為異步模型。事件驅動編程的工作依賴於程序中發生的事件。
除此之外,它還依賴於程序的事件循環,該循環總是在程序中監聽新的傳入事件。一旦一個事件循環在程序中開始,那麼只有事件將決定執行什麼和以什麼順序執行。
查看下面的事件循環流程圖,了解事件驅動編程中事件的工作方式:
事件驅動pexpect
模塊
asyncio
模塊是在 3.4 版本中添加到 Python 中的,它在 Python 的所有更高版本中都可用。Asyncio 模塊為使用程序中的 coroutines 將並發代碼編寫為單線程提供了非常好的基礎設施。
在 Python 的 asyncio
模塊中,在進行事件驅動編程時使用了以下不同的概念:
- 事件循環
- 期貨
- 協程
- @asyncio .裝飾程式
- 任務
- 運輸
- 和協議
讓我們詳細了解 asyncio
模塊使用的所有這些不同的概念,並了解它們在進行事件驅動編程時是如何工作的。
事件循環
事件循環是 asyncio
模塊的一項功能,用於處理計算程序中發生的所有事件。當整個程序正在執行時,事件循環的行為就像是在繞路,它還會跟蹤已執行的事件和新的傳入事件。asyncio
模塊的一個主要優點是,每個進程只允許一個事件循環。
在 asyncio
模塊中,我們有一些方法可以用來管理代碼中的事件循環。asyncio
模塊中提供了以下方法。
- time() – 我們可以根據事件循環中存在的內部時鐘,用這個方法將當前時間返回給用戶。
- loop = get_event_loop() – 通過使用這個方法,我們將根據程序中執行的當前上下文得到事件循環作為回報。
- call_soon(CallbackFunction,ArgumentGiven) – 有了這個函數,我們可以安排一個回調函數儘快被調用。當控件返回到事件循環並且 call_soon()返回後,參數中給出的回調函數將被調用。
- call late(time to _ delived,CallbackFunction,ArgumentGiven) – 使用這個方法,我們可以安排在我們提供的時間延遲(以秒為單位)之後調用方法中給出的回調函數。
- new_event_loop() – 使用這個方法,我們可以創建並返回一個新的事件 loop 項目。
- set_event_loop() – 藉助這個方法,我們可以為從程序執行到循環的當前上下文設置事件循環。
- run_forever() – 通過在程序中使用 loop.run_forever()方法,我們可以運行一個循環,直到調用 stop()方法。
現在,我們將在下面的示例中查看一個 Python 程序,其中我們將使用事件循環方法,即 get_event_loop()方法。通過使用這種方法,我們將打印我們在事件內部給出的命令。
示例:看看下面這個包含事件循環的 Python 程序:
# Importing asyncio module in the program
import asyncio
# A default function with event loops method
def loopText(loop):
# A text printing command
print('Printing this text through the event loop')
loop.stop() # Stopping the loop
loop = asyncio.get_event_loop() # Using get_event_loop() method to print the text
loop.call_soon(loopText, loop) # Using call_soon() method from event loops
loop.run_forever() # run_forever() on event loop
loop.close() # Closing the loop
輸出
Printing this text through the event loop
說明:
我們首先在程序中導入了 asyncio
模塊,以使用事件循環方法。
之後,我們定義了一個默認函數,在這個函數中,我們給出了「loop」作為參數,並在函數內部給出了打印命令。我們使用事件循環中的 stop()方法來停止事件。
之後,我們在循環參數上使用 get_event_loop()方法打印默認函數中的文本。然後,在 call_soon()事件循環方法中,我們使用函數的函數名和參數作為參數。最後,我們使用了 run_forever()和 close()事件循環方法。
期貨
asyncio
模塊中給出的未來類與 concurrent.futures 方法兼容。asyncio
模塊中給出的未來類代表程序中的計算,這還沒有完成。
期貨和期貨之間有一些主要的區別
- 我們在將來的類中用 add_done_callback()方法註冊的回調函數將始終只通過事件循環中的 call_soon()方法來調用。
- future 類中的 exception()和 result()方法不會接受超時或給定時間的參數,當這些函數的 future 尚未完成時,它們會在輸出中顯示一個錯誤。
- 我們不能將 asyncio.futures.Future 類與 concurrent.futures 包中的 as_completed()或 wait()函數一起使用,因為它與它們不兼容。
現在,我們將在下面的示例中查看一個 Python 程序,其中我們將使用 asyncio
模塊中的未來類方法,並在輸出中打印文本。
示例:
# Importing asyncio module in the program
import asyncio
# A default function from the async module using future parameter in it
async def myFunction(future):
await asyncio.sleep(2) # Using sleep() function of asyncio module
future.set_result('This text is printed using future class methods!') # Printing text from future parameter
# Using get_event_loop() method from event loop
loop = asyncio.get_event_loop()
future = asyncio.Future() # Using future() class method
# Calling default function from future class method
asyncio.ensure_future(myFunction(future))
# Using try & finally method future parameter of function
try:
loop.run_until_complete(future)
print(future.result()) # printing result from future class
finally:
loop.close() # finally closing the loop
輸出
This text is printed using future class methods!
說明:
我們首先定義了一個默認函數,即「myFunction」,future 作為參數。在函數內部,我們使用 sleep()方法作為執行的兩秒暫停。
然後,我們使用未來的類方法給出了我們想要打印在結果中的文本。我們在程序中使用了事件循環中的 get_event_loop 方法。然後,我們對默認函數中給出的 future 參數使用了 future()類方法。
現在,我們可以在輸出中打印文本,就像我們在其中使用了未來一樣。為了打印輸出中的文本,我們使用了 try 和 finish 方法,其中 try 方法調用了 printing 命令,finish 方法使用 close()方法關閉了循環。
協程
asyncio
模塊內部的協同概念非常類似於線程模塊線程對象中的協同概念。
asyncio
模塊中的協同概念是子程序概念的推廣形式。
我們甚至可以在程序執行期間掛起一個協程,這樣掛起的協程將等待用戶給出的外部處理。只有在外部處理完成後,暫停的協程才會返回到上次暫停的位置。
在 asyncio
模塊協程中,我們可以使用以下兩種方式來幫助我們在程序中實現協程:
- @asyncio .裝飾程式
- 異步定義函數()
讓我們通過在 Python 程序中使用它們的實現來理解這兩種方式。
1 .@asyncio .裝飾例程〔t1〕
我們可以利用帶有 asyncio
模塊裝飾器的生成器,即@asyncio.coroutine 裝飾器,在程序內部實現協程。我們可以通過下面的例子理解協程和 decorator 的實現。
示例:看看下面的 Python 程序:
# Importing asyncio module in the program
import asyncio
# Using @asyncio.coroutine decorator to implement coroutines
@asyncio.coroutine
# Using a default function with coroutine implementation
def operationCoroutine():
print("This text is present inside the coroutine of the asyncio module!") # Printing text inside coroutine
loop = asyncio.get_event_loop() # Using get_event_loop() method to print text
try:
loop.run_until_complete(operationCoroutine()) # Using run_until_complete() loop method on default function
finally:
loop.close() # closing the loop
輸出
This text is present inside the coroutine of the asyncio module!
說明:
導入 asyncio
模塊後,我們使用了@asyncio.coroutine 裝飾器。然後,我們使用一個默認函數來使用協程方法來獲取文本。之後,我們使用事件循環中的 get_event_loop()方法打印輸出中的文本。最後,我們對默認函數使用了「try and finally」方法,並使用 close()函數關閉了程序中的循環。
2。異步定義函數()
我們可以說 async def 函數()是 asyncio
模塊實現協程的最通用的方法。我們可以通過下面的例子理解這個用 def 函數()實現 coroutines 的方法。
示例:看看下面的 Python 程序:
# Importing asyncio module in the program
import asyncio
# Using async def function() to implement coroutines
async def operationCoroutine():
print("This text is present inside the coroutine of the asyncio module!") # Printing text inside coroutine
loop = asyncio.get_event_loop() # Using get_event_loop() method to print text
try: loop.run_until_complete(operationCoroutine()) # Using run_until_complete() loop method on default function
finally:
loop.close() # closing the loop
輸出
This text is present inside the coroutine of the asyncio module!
說明:
像第一種實現協程的方法一樣,我們在這個方法中也遵循了同樣的路徑。在這個方法中,我們沒有使用裝飾器,然後為 coroutines 定義默認函數,而是直接使用 asyncio
模塊的 async def operationCoroutine()函數來實現 coroutines。
任務
Tasks 是 asyncio
模塊中給出的一個子類,負責在事件循環中以並行執行的方式執行 asyncio 協程。我們可以通過使用一個 Python 程序來執行協同工作來理解任務子類的工作。
例
# Importing asyncio module in the program
import asyncio
# Importing time module
import time
# Using async default function()
async def Task_ex(n):
time.sleep(2) # sleep() function of time module
print("Loop event is processing coroutine no: {}".format(n)) # given printing tasks to print in output
# Generating tasks with async default function
async def Generator_task():
# looping over tasks using for loop
for i in range(10):
asyncio.ensure_future(Task_ex(i))
# After completing loop
print("All given tasks are completed")
asyncio.sleep(2)
loop = asyncio.get_event_loop() # printing in output using event loop method
loop.run_until_complete(Generator_task()) # Running the loop
loop.close() # Closing the loop
輸出
Loop event is processing coroutine no: 0
Loop event is processing coroutine no: 1
Loop event is processing coroutine no: 2
Loop event is processing coroutine no: 3
Loop event is processing coroutine no: 4
Loop event is processing coroutine no: 5
Loop event is processing coroutine no: 6
Loop event is processing coroutine no: 7
Loop event is processing coroutine no: 8
Loop event is processing coroutine no: 9
All given tasks are completed
說明:
我們在程序中導入了 asyncio 和時間模塊來使用它的功能。然後,我們使用異步默認函數來設置打印已處理的協程的任務。
我們使用時間模塊的 sleep()函數,在打印每個執行的協程後,給出 2 秒的休息時間。
然後,我們使用另一個異步默認函數來設置其中任務的循環。完成循環後,該功能將打印「任務已完成」最後,我們使用事件循環方法來運行和關閉程序中的循環。
運輸
Transports 是 asyncio
模塊中提供給我們的類,我們可以使用它們在程序中實現各種類型的通信。傳輸類不是線程安全的,我們總是必須在通信通道建立後將它們與協議實例配對。
在 asyncio 傳輸類中,程序中可以從基本傳輸類繼承以下類型的傳輸:
- 數據報傳輸:數據報傳輸是我們用來發送數據的接口。
- 讀傳輸:讀傳輸是只讀模式傳輸類的接口。
- 寫傳輸:這個傳輸是繼承的傳輸類的接口,只有隻寫模式。
- 基本子流程傳輸:基本子流程傳輸類的功能與基本傳輸類非常相似。
在所有上述繼承的傳輸類中,只有以下不同類型的方法隨後從基本傳輸類中過渡出來:
- is_closing(): 只有當參數中給定的傳輸類已經關閉並且正在關閉時,此方法才會返回 true。
- close(): 此方法用於關閉程序中正在運行的當前傳輸類。
- get_protocol(): 我們可以使用 transport 類中的 get_protocol()方法來獲取當前協議作為回報。
- get_extra_info(className,default = none ):我們可以使用這個方法獲取一些關於我們在參數中給出的傳輸類的附加信息。
協議
在 asyncio
模塊中,我們提供了幾個基類,可以用它們在子類中實現我們的網絡協議。我們可以將這樣的類與傳輸類結合使用。該協議將請求輸出數據並解析輸入數據,而傳輸類負責緩衝和實際輸入/輸出
以下是三類協議:
- 協議類:它是協議中的基類,我們可以用它來實現與 SSL 和 TCP 傳輸一起使用的流協議。
- 數據報協議類:它是協議中的另一個基類,我們可以用來實現與 UDP 傳輸一起使用的數據報協議。
- 子進程協議類:我們可以使用協議中的這個基類來實現使用一組單向管道來傳遞子進程的各種協議。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/276742.html