目錄
什麼是協程
生成器協程
两种协程对比
实战案例
首頁 後端開發 Python教學 Python協程的實作方式有哪些

Python協程的實作方式有哪些

May 20, 2023 am 11:08 AM
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())
登入後複製
###結果輸出:# ########[root@workhost k8s]# python3 test.py ###Main started###Coroutine started###Coroutine finished###Main finished#########繼續看一下執行過程:############main 函數開始執行,列印出Main started。 ############呼叫 coroutine 函數,將其作為協程物件運行。 ############在 coroutine 函數中,印出 Coroutine started。 ############在 coroutine 函數中,使用 await asyncio.sleep(1) 暫停函數的執行,等待1秒鐘。 ############在1秒鐘後,恢復 coroutine 函數的執行,並印出 Coroutine finished。 ############main 函數復原執行,列印出 Main finished。 ############在上面的程式碼中,使用async 關鍵字定義了一個原生協程函數coroutine,並在其中使用await 關鍵字來暫停函數的執行,等待非同步I/O 操作的完成。使用原生協程可以編寫並發非同步程式碼,從而提高程式碼的效率和效能。 ###

两种协程对比

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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1319
25
PHP教程
1269
29
C# 教程
1248
24
PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

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

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

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

sublime怎麼運行代碼python sublime怎麼運行代碼python Apr 16, 2025 am 08:48 AM

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

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

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

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

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

Golang vs. Python:性能和可伸縮性 Golang vs. Python:性能和可伸縮性 Apr 19, 2025 am 12:18 AM

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

vscode在哪寫代碼 vscode在哪寫代碼 Apr 15, 2025 pm 09:54 PM

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

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

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

See all articles