Python協程的實作方式有哪些
什麼是協程
在 Python 中,協程(Coroutine)是一種輕量級的並發程式設計方式,可以透過協作式多任務來實現高效的並發執行。使用 yield 關鍵字掛起函數的執行,以及儲存目前執行狀態,是協程的特殊之處。因此,協程可視為一種特殊的生成器函數。當協程被掛起時,可以使用 send 方法來恢復其執行,並在恢復後傳回一個值。
在 Python 3.4 以前,常使用 yield 關鍵字來實現協程,即稱為「生成器協程」。在 Python 3.4 引入了 asyncio 模組後,可以使用 async/await 關鍵字來定義協程函數,稱為「原生協程」。
協程相比於執行緒和進程,具有以下優點:
輕量級:協程的上下文切換成本很小,可以在單執行緒內並發執行大量的協程。
低延遲:協程的執行過程中,沒有執行緒切換的開銷,也沒有加鎖解鎖的開銷,可以更快地回應外部事件。
高效能:協程的程式碼通常比多執行緒和多進程的程式碼更簡潔可讀,維護成本更低。
協程的使用場景包括網路程式設計、非同步 I/O、資料流處理、高並發任務等。
生成器協程
在 Python 3 中,生成器協程(Generator Coroutine)是指使用生成器函數來實現的協程。生成器函數是一種特殊的函數,其傳回一個生成器對象,可以透過 yield 語句暫停函數的執行,然後在下次呼叫生成器物件的 「next」() 方法時繼續執行。
下面給出一個簡單的生成器協程的範例,其中包含一個生成器函數coroutine 和一個簡單的非同步I/O 操作:
import asyncio def coroutine(): print('Coroutine started') while True: result = yield print('Coroutine received:', result) async def main(): print('Main started') c = coroutine() next(c) c.send('Hello') await asyncio.sleep(1) c.send('World') print('Main finished') asyncio.run(main())
結果輸出:
[root@workhost k8s]# python3 test.py
Main started
Coroutine started
Coroutine received: Hello
Coroutine received: World
Main finished
##4
main 函數開始執行,列印出Main started。
#來看一下,上面程式碼的執行過程:
- 建立一個生成器物件 c,呼叫 next(c) 使其執行到第一個 yield 語句處暫停。
- 使用 c.send('Hello') 恢復生成器函數的執行,並將 'Hello' 作為生成器函數的傳回值。
- 在等待1秒鐘的過程中,main 函數暫停執行,等待事件循環啟動下一次任務。
- 在等待1秒鐘後,使用 c.send('World') 繼續執行生成器函數,並將 'World' 作為生成器函數的傳回值。
- main 函數復原執行,列印出 Main finished。
- 透過使用生成器函數 coroutine,這段程式碼實現了一個簡單的協程。生成器函數透過使用 yield 語句暫停函數的執行,然後可以透過 send 方法恢復函數的執行,並將值傳遞給生成器函數。透過這種方式,可以使用生成器函數實現非同步並發。使用生成器函數接受非同步 I/O 操作的結果,並將其列印出來,如範例所示。
原生協程
Python 3引進原生協程(Native Coroutine)作為一種新協程類型。原生協程是透過使用 async/await 關鍵字來定義的,與生成器協程不同,它們可以像普通函數一樣使用 return 語句傳回值,而不是使用 yield 語句。
下面給出一個簡單的原生協程範例,其中包含一個async 關鍵字修飾的協程函數coroutine 和一個簡單的非同步I/O 操作:
import asyncio async def coroutine(): print('Coroutine started') await asyncio.sleep(1) print('Coroutine finished') async def main(): print('Main started') await coroutine() print('Main finished') asyncio.run(main())
两种协程对比
Python 3 中,原生协程和生成器协程是不同的协程实现方式,它们分别具有独特的特点和适用场景。下面,通过对比它们的区别和优缺点,才可以更好地理解它们之间的异同,以便选择适合自己的协程实现方式,从而更好地编写高效、可维护的异步程序。
1.区别:
定义方式不同:原生协程使用 async/await 关键字来定义,而生成器协程使用 yield 关键字来定义。
返回方式不同:原生协程使用 return 语句来返回结果,而生成器协程使用 yield 语句来返回结果。
调用方式不同:原生协程使用 await 关键字来调用,而生成器协程使用 yield from 或 yield 语句来调用。
原生协程与生成器协程的实现方式不同,前者使用 asyncio 库,后者则是 Python 语言内置的特性。
2.优缺点:
原生协程的优点:
代码简洁易懂:使用 async/await 关键字,可以编写出更简洁易懂的协程代码。
性能更高:原生协程不需要创建生成器对象,也不需要通过 yield 语句来控制函数的执行流程,因此能够更加高效地处理异步操作。
支持异步 I/O 和任务处理:原生协程可以支持异步 I/O 操作和并发任务处理,可以在处理异步操作时更加灵活。
原生协程的缺点:
兼容性差:原生协程是 Python 3.5 版本之后才引入的新特性,因此在旧版本的 Python 中无法使用。
异常处理不方便:原生协程在处理异常时比较麻烦,需要使用 try/except 语句来处理。
生成器协程的优点:
兼容性好:生成器协程是 Python 2 和 Python 3 都支持的特性。
可读性好:生成器协程使用 yield 关键字来实现,代码逻辑清晰易懂。
异常处理方便:生成器协程在处理异常时比较方便,可以使用 try/except 语句来处理。
生成器协程的缺点:
性能相对较低:生成器协程需要创建生成器对象,也需要通过 yield 语句来控制函数的执行流程,因此处理异步操作时性能相对较低。
功能有限:生成器协程不能像原生协程一样支持异步 I/O 操作和任务处理。
实战案例
接下来,模拟一个场景,假设实现一个异步的批量处理任务的工具,使用原生协程来实现。
看下面代码:
import asyncio import random async def batch_process_task(tasks, batch_size=10): # 将任务列表划分为多个批次 for i in range(0, len(tasks), batch_size): batch = tasks[i:i+batch_size] # 使用原生协程来异步处理每个批次的任务 await asyncio.gather(*[process_task(task) for task in batch]) async def process_task(task): # 模拟任务处理过程 await asyncio.sleep(random.uniform(0.5, 2.0)) print("Task {} processed".format(task)) async def main(): # 构造任务列表 tasks = [i for i in range(1, 101)] # 并发处理批量任务 await batch_process_task(tasks, batch_size=10) if __name__ == '__main__': asyncio.run(main())
输出:
[root@workhost k8s]# python3 test.py
Task 9 processed
Task 10 processed
Task 1 processed
Task 8 processed
Task 6 processed
Task 4 processed
Task 3 processed
Task 2 processed
Task 5 processed
...
...
batch_process_task函数使用原生协程来处理每个批次的任务,而process_task函数则是处理每个任务的函数。在main函数中,任务列表会被构造,并使用batch_process_task函数来异步地处理批量任务。
以上是Python協程的實作方式有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

在 Sublime Text 中運行 Python 代碼,需先安裝 Python 插件,再創建 .py 文件並編寫代碼,最後按 Ctrl B 運行代碼,輸出會在控制台中顯示。

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Golang在性能和可擴展性方面優於Python。 1)Golang的編譯型特性和高效並發模型使其在高並發場景下表現出色。 2)Python作為解釋型語言,執行速度較慢,但通過工具如Cython可優化性能。

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。
