Python 協程庫 Asyncio

Mondo 科技 更新 2024-03-03

Python 在 3 中我在版本 5 中新增了 asyncio,但在版本 3 中使用後似乎並不容易使用7、asyncio 有了很大的改進,用起來還不錯,asyncio 引入了 async await 語法,有點類似於 nodejs。

最簡單的例子:

import asyncioasync def main():print('hello ..') await asyncio.sleep(1) print('...world!')# python 3.7+asyncio.run(main())
例如,PHP 的 Swoole 擴充套件也是基於協程的,但使用起來不如 Python 方便,而且 Swoole 不提供非同步 await 語法。 Asyncio 提供了 Create Task 來建立協程任務,可以與 Swoole 的 go 函式進行比較

async def main():task1 = asyncio.create_task( say_after(1, 'hello')) task2 = asyncio.create_task( say_after(2, 'world')) print(f"started at ") await task1 await task2 print(f"finished at ")
asyncio 還提供了許多幫助程式函式,例如 asyncioGather 用於同時執行多個協程任務,相當於之前使用 Swoole 實現的 groupwait。 對應的 swoole 通道也有乙個版本的 asyncioqueue。還有多個佇列,例如 priorityqueue 和 lifoqueue,因此 Asyncio 也完全適合 CSP 程式設計模型。

使用 asyncio 建立 TCP 服務:

import asyncioasync def handle echo(reader, writer): while true: 確定 EOF 終止符以關閉鏈結 if readerat_eof():break data = await reader.readline() message = data.decode() addr = writer.get_extra_info('peername') print(f"received from ") print(f"send: ") writer.write(data) await writer.drain() print("close the connection") writer.close()async def tcp_server_task():server = await asyncio.start_server(handle_echo, '127.0.0.1', 8888) addr = server.sockets[0].getsockname() print(f'serving on ') async with server: await server.serve_forever()async def main():task = asyncio.create_task(tcp_server_task())await taskasyncio.run(main())
現在我們假設我們需要建立乙個集中的TCP日誌採集服務,並將TCP埠接收到的日誌儲存在PostgreSQL或者MySQL中,日誌請求的數量會比較大,所以我們需要有良好的效能,使用以下簡單的實現方式:

import asynciofrom psycopg2.pool import **connectionpoolfrom datetime import datetimeclass asynctask: def __init__(self): self.task_queue = asyncio.queue() self.db_pool = **connectionpool( 2, 20, dbname='echoes', host='192.168.2.10', user='twn39', password='tangweinan') async def handle echo(self, reader, writer): while true: 確定 EOF 終止符以關閉鏈結 if readerat_eof():break data = await reader.readline() message = data.decode() self.task_queue.put_nowait(message.strip())writer.write("ok".encode())await writer.drain() print("close the connection") writer.close() async def tcp_server_task(self): server = await asyncio.start_server(self.handle_echo, '127.0.0.1', 8888) addr = server.sockets[0].getsockname() print(f'serving on ') async with server: await server.serve_forever() async def consume_task(self, name: str): while true: data = await self.task_queue.get() conn = self.db_pool.getconn() print(conn) cur = conn.cursor() cur.execute("insert into logs (level, message, created_at) values (%s, %s, %s)", (200, 'log test', datetime.now() conn.commit() self.db_pool.putconn(conn) print(f'work: consume data: ') self.task_queue.task_done()if __name__ == '__main__': async def main():async_task = asynctask() task = asyncio.create_task(async_task.tcp_server_task())task1 = asyncio.create_task(async_task.consume_task('worker-1')) task2 = asyncio.create_task(async_task.consume_task('worker-2')) await asyncio.gather(task, task1, task2, return_exceptions=true) asyncio.run(main())
程式中引入了 Queue,它可以非同步寫入資料庫以提高高峰請求期間的穩定性,我們建立了三個主要任務,乙個是監聽 TCP 埠,獲取日誌資料,將日誌放入佇列中,另外兩個是消耗佇列,當佇列中有資料時寫入資料庫, 並在沒有資料時等待資料。

* 有兩個無限迴圈(實際上是三個),程式執行時,相當於並行,但實際上它是單執行緒的,協程可以中斷,當多個協程執行時,其實函式之間切換,但切換時間很短,所以反映在並行上。 多執行緒程式設計是由作業系統實現的,因此在它們之間切換的成本相對較高,而協程則由使用者決定何時切換,也稱為使用者端線程。

相關問題答案

    對 Python Web 庫請求的深入探索

    Python 網路庫 requests深入探索 隨著網際網絡的發展,網路程式設計和資料抓取變得越來越重要。在python中,requests該庫已成為網路請求的標準庫,因為它提供了乙個簡潔 使用者友好的 API 來傳送 HTTP 請求。本文將深入探討 requests庫的功能和用法。.引言 requ...

    讓我們簡要談談程序、執行緒和協程

    要成為一名優秀的軟體工程師,流程和執行緒是必須了解和掌握的知識點,不僅因為它們是電腦科學的基礎知識,還因為知道如何在正確的時間使用它們可以提高程式的執行效率,即提高效能。在了解程序和執行緒之前,我們先來談談程式,其實所謂的程式就是工程師編寫的 集合,程式經過編譯器或直譯器的處理,轉換成機器可以理解和...

    如何在 Python 中檢視庫版本?

    Python 有乙個非常獨特的優勢,它內建了很多第三方庫,開箱使用非常方便,比如 numpy pandas matplotlib 等。當我們使用python庫時,有時我們需要檢查它的版本,那麼如何在python中檢查庫版本呢?以下是常用方法的介紹。.使用 pip 命令檢視庫版本 pip 是乙個 Py...

    Seaborn 是乙個老牌的 Python 視覺化庫,經過十年的積累,已經發展成為一種新的使用方式

    在 Python 中資料視覺化在該領域,matplotlib 一直是使用最廣泛的視覺化庫。然而,其操作的複雜性一直困擾著使用者。為了解決這個問題,seaborn它應運而生,並因其簡化的操作流程而受到廣泛關注。儘管如此,seaborn它們的使用方式仍然存在一些缺陷。經過長達 年的拋光,seaborn該...

    Python 程式設計 01 第三方庫安裝

    Python因其強大而廣泛的第三方庫支援而成為人工智慧時代的程式語言之一,支援各種豐富的庫,用於科學計算 計算機視覺 數字影象處理和自然語言處理。通過PIP包管理器,可以實現快速安裝和環境配置,方便自己演算法的快速開發和實現,尤其是人工智慧時代深度神經網路演算法的實驗開發。python packag...