中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python協程的實現方式有哪些

發布時間:2023-04-27 17:54:36 來源:億速云 閱讀:135 作者:iii 欄目:開發技術

這篇文章主要介紹“Python協程的實現方式有哪些”,在日常操作中,相信很多人在Python協程的實現方式有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”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

來看一下,上面代碼的執行過程:

  • 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協程的實現方式有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

连平县| 莱西市| 于田县| 阿图什市| 白山市| 涪陵区| 汽车| 中超| 友谊县| 屏边| 南投县| 视频| 古丈县| 红原县| 南澳县| 凌源市| 柞水县| 大渡口区| 淮滨县| 和平县| 霍林郭勒市| 新营市| 江津市| 台湾省| 泰来县| 大余县| 民权县| 宜君县| 阿坝| 太湖县| 新兴县| 泽库县| 南通市| 朔州市| 牙克石市| 隆化县| 屯留县| 延川县| 阿勒泰市| 安龙县| 保康县|