欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python協(xié)程的2種實(shí)現(xiàn)方式分享

 更新時(shí)間:2023年04月27日 09:06:07   作者:不背鍋運(yùn)維  
在?Python?中,協(xié)程(Coroutine)是一種輕量級(jí)的并發(fā)編程方式,可以通過協(xié)作式多任務(wù)來實(shí)現(xiàn)高效的并發(fā)執(zhí)行。本文主要介紹了Python實(shí)現(xiàn)協(xié)程的2種方式,希望對(duì)大家有所幫助

什么是協(xié)程

在 Python 中,協(xié)程(Coroutine)是一種輕量級(jí)的并發(fā)編程方式,可以通過協(xié)作式多任務(wù)來實(shí)現(xiàn)高效的并發(fā)執(zhí)行。協(xié)程是一種特殊的生成器函數(shù),通過使用 yield 關(guān)鍵字來掛起函數(shù)的執(zhí)行,并保存當(dāng)前的執(zhí)行狀態(tài)。協(xié)程的執(zhí)行可以通過 send 方法來恢復(fù),并在下一次掛起時(shí)返回一個(gè)值。

在 Python 3.4 之前,協(xié)程通常使用 yield 關(guān)鍵字來實(shí)現(xiàn),稱為“生成器協(xié)程”。在 Python 3.4 引入了 asyncio 模塊后,可以使用 async/await 關(guān)鍵字來定義協(xié)程函數(shù),稱為“原生協(xié)程”。

協(xié)程相比于線程和進(jìn)程,具有以下優(yōu)點(diǎn):

  • 輕量級(jí):協(xié)程的上下文切換成本很小,可以在單線程內(nèi)并發(fā)執(zhí)行大量的協(xié)程。
  • 低延遲:協(xié)程的執(zhí)行過程中,沒有線程切換的開銷,也沒有加鎖解鎖的開銷,可以更快地響應(yīng)外部事件。
  • 高效性:協(xié)程的代碼通常比多線程和多進(jìn)程的代碼更加簡潔和可讀,維護(hù)成本更低。

協(xié)程的使用場景包括網(wǎng)絡(luò)編程、異步 I/O、數(shù)據(jù)流處理、高并發(fā)任務(wù)等。

生成器協(xié)程

在 Python 3 中,生成器協(xié)程(Generator Coroutine)是指使用生成器函數(shù)來實(shí)現(xiàn)的協(xié)程。生成器函數(shù)是一種特殊的函數(shù),其返回一個(gè)生成器對(duì)象,可以通過 yield 語句暫停函數(shù)的執(zhí)行,然后在下一次調(diào)用生成器對(duì)象的 「next」() 方法時(shí)繼續(xù)執(zhí)行。

下面給出一個(gè)簡單的生成器協(xié)程的示例,其中包含一個(gè)生成器函數(shù) coroutine 和一個(gè)簡單的異步 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())

結(jié)果輸出:

[root@workhost k8s]# python3 test.py 
Main started
Coroutine started
Coroutine received: Hello
Coroutine received: World
Main finished

來看一下,上面代碼的執(zhí)行過程:

  • main 函數(shù)開始執(zhí)行,打印出 Main started。
  • 創(chuàng)建一個(gè)生成器對(duì)象 c,調(diào)用 next(c) 使其執(zhí)行到第一個(gè) yield 語句處暫停。
  • 使用 c.send('Hello') 恢復(fù)生成器函數(shù)的執(zhí)行,并將 'Hello' 作為生成器函數(shù)的返回值。
  • 在等待1秒鐘的過程中,main 函數(shù)暫停執(zhí)行,等待事件循環(huán)發(fā)起下一次任務(wù)。
  • 在等待1秒鐘后,使用 c.send('World') 繼續(xù)執(zhí)行生成器函數(shù),并將 'World' 作為生成器函數(shù)的返回值。
  • main 函數(shù)恢復(fù)執(zhí)行,打印出 Main finished。

在上面的代碼中,使用生成器函數(shù) coroutine 實(shí)現(xiàn)了一個(gè)簡單的協(xié)程。生成器函數(shù)通過使用 yield 語句暫停函數(shù)的執(zhí)行,然后可以通過 send 方法恢復(fù)函數(shù)的執(zhí)行,并將值傳遞給生成器函數(shù)。通過這種方式,可以使用生成器函數(shù)實(shí)現(xiàn)異步并發(fā)。在上面的示例中,使用生成器函數(shù)接收并打印異步 I/O 操作的結(jié)果。

原生協(xié)程

Python 3 引入了原生協(xié)程(Native Coroutine)作為一種新的協(xié)程類型。原生協(xié)程是通過使用 async/await 關(guān)鍵字來定義的,與生成器協(xié)程不同,它們可以像普通函數(shù)一樣使用 return 語句返回值,而不是使用 yield 語句。

下面給出一個(gè)簡單的原生協(xié)程示例,其中包含一個(gè) async 關(guān)鍵字修飾的協(xié)程函數(shù) coroutine 和一個(gè)簡單的異步 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())

結(jié)果輸出:

[root@workhost k8s]# python3 test.py 
Main started
Coroutine started
Coroutine finished
Main finished

繼續(xù)看一下執(zhí)行過程:

  • main 函數(shù)開始執(zhí)行,打印出 Main started。
  • 調(diào)用 coroutine 函數(shù),將其作為一個(gè)協(xié)程對(duì)象運(yùn)行。
  • 在 coroutine 函數(shù)中,打印出 Coroutine started。
  • 在 coroutine 函數(shù)中,使用 await asyncio.sleep(1) 暫停函數(shù)的執(zhí)行,等待1秒鐘。
  • 在1秒鐘后,恢復(fù) coroutine 函數(shù)的執(zhí)行,并打印出 Coroutine finished。
  • main 函數(shù)恢復(fù)執(zhí)行,打印出 Main finished。

在上面的代碼中,使用 async 關(guān)鍵字定義了一個(gè)原生協(xié)程函數(shù) coroutine,并在其中使用 await 關(guān)鍵字來暫停函數(shù)的執(zhí)行,等待異步 I/O 操作的完成。通過這種方式,可以在原生協(xié)程中編寫異步并發(fā)代碼,從而提高代碼的性能和效率。

兩種協(xié)程對(duì)比

Python 3 中原生協(xié)程和生成器協(xié)程是兩種不同的協(xié)程實(shí)現(xiàn)方式,它們各自有自己的特點(diǎn)和適用場景。下面,通過對(duì)比它們的區(qū)別和優(yōu)缺點(diǎn),才可以更好地理解它們之間的異同,以便選擇適合自己的協(xié)程實(shí)現(xiàn)方式,從而更好地編寫高效、可維護(hù)的異步程序。

1.區(qū)別:

  • 定義方式不同:原生協(xié)程使用 async/await 關(guān)鍵字來定義,而生成器協(xié)程使用 yield 關(guān)鍵字來定義。
  • 返回方式不同:原生協(xié)程使用 return 語句來返回結(jié)果,而生成器協(xié)程使用 yield 語句來返回結(jié)果。
  • 調(diào)用方式不同:原生協(xié)程使用 await 關(guān)鍵字來調(diào)用,而生成器協(xié)程使用 yield from 或 yield 語句來調(diào)用。
  • 內(nèi)部實(shí)現(xiàn)不同:原生協(xié)程通過 asyncio 庫來實(shí)現(xiàn),而生成器協(xié)程是 Python 語言內(nèi)置的特性。

2.優(yōu)缺點(diǎn):

原生協(xié)程的優(yōu)點(diǎn):

  • 代碼簡潔易懂:使用 async/await 關(guān)鍵字,可以編寫出更簡潔易懂的協(xié)程代碼。
  • 性能更高:原生協(xié)程不需要?jiǎng)?chuàng)建生成器對(duì)象,也不需要通過 yield 語句來控制函數(shù)的執(zhí)行流程,因此能夠更加高效地處理異步操作。
  • 支持異步 I/O 和任務(wù)處理:原生協(xié)程可以支持異步 I/O 操作和并發(fā)任務(wù)處理,可以在處理異步操作時(shí)更加靈活。

原生協(xié)程的缺點(diǎn):

  • 兼容性差:原生協(xié)程是 Python 3.5 版本之后才引入的新特性,因此在舊版本的 Python 中無法使用。
  • 異常處理不方便:原生協(xié)程在處理異常時(shí)比較麻煩,需要使用 try/except 語句來處理。

生成器協(xié)程的優(yōu)點(diǎn):

  • 兼容性好:生成器協(xié)程是 Python 2 和 Python 3 都支持的特性。
  • 可讀性好:生成器協(xié)程使用 yield 關(guān)鍵字來實(shí)現(xiàn),代碼邏輯清晰易懂。
  • 異常處理方便:生成器協(xié)程在處理異常時(shí)比較方便,可以使用 try/except 語句來處理。

生成器協(xié)程的缺點(diǎn):

  • 性能相對(duì)較低:生成器協(xié)程需要?jiǎng)?chuàng)建生成器對(duì)象,也需要通過 yield 語句來控制函數(shù)的執(zhí)行流程,因此處理異步操作時(shí)性能相對(duì)較低。
  • 功能有限:生成器協(xié)程不能像原生協(xié)程一樣支持異步 I/O 操作和任務(wù)處理。

實(shí)戰(zhàn)案例

接下來,模擬一個(gè)場景,假設(shè)實(shí)現(xiàn)一個(gè)異步的批量處理任務(wù)的工具,使用原生協(xié)程來實(shí)現(xiàn)。

看下面代碼:

import asyncio
import random

async def batch_process_task(tasks, batch_size=10):
    # 將任務(wù)列表劃分為多個(gè)批次
    for i in range(0, len(tasks), batch_size):
        batch = tasks[i:i+batch_size]
        # 使用原生協(xié)程來異步處理每個(gè)批次的任務(wù)
        await asyncio.gather(*[process_task(task) for task in batch])

async def process_task(task):
    # 模擬任務(wù)處理過程
    await asyncio.sleep(random.uniform(0.5, 2.0))
    print("Task {} processed".format(task))

async def main():
    # 構(gòu)造任務(wù)列表
    tasks = [i for i in range(1, 101)]
    # 并發(fā)處理批量任務(wù)
    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函數(shù)使用原生協(xié)程來處理每個(gè)批次的任務(wù),而process_task函數(shù)則是處理每個(gè)任務(wù)的函數(shù)。main函數(shù)則是構(gòu)造任務(wù)列表,并且使用batch_process_task函數(shù)來異步地處理批量任務(wù)。

到此這篇關(guān)于Python協(xié)程的2種實(shí)現(xiàn)方式分享的文章就介紹到這了,更多相關(guān)Python協(xié)程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論