Python使用asyncio實(shí)現(xiàn)異步操作的示例
在 Python 中,使用 async
和 await
可以非常高效地處理復(fù)雜的異步 I/O 操作。它們的主要目的是簡化異步編程模型,使代碼可讀性更好,并且能夠在 I/O 操作時(shí)不阻塞主線程。下面是如何有效地利用它們來實(shí)現(xiàn)復(fù)雜異步 I/O 操作的指南:
1. 基礎(chǔ)概念
async def
:定義一個(gè)異步函數(shù),這樣的函數(shù)在調(diào)用時(shí)不會(huì)立即執(zhí)行,而是返回一個(gè)協(xié)程對象。await
:用于等待一個(gè)異步操作(如 I/O 操作)的結(jié)果,釋放當(dāng)前函數(shù)持有的 CPU 以便其他協(xié)程能夠執(zhí)行。asyncio
:Python 的標(biāo)準(zhǔn)庫提供了強(qiáng)大的異步 I/O 庫,包含了事件循環(huán)、任務(wù)、以及各種異步 I/O 操作的工具。
2. 實(shí)現(xiàn)異步 I/O 的步驟
2.1 定義異步函數(shù)
使用 async def
定義異步函數(shù),可以在函數(shù)內(nèi)部使用 await
調(diào)用異步任務(wù)。例如,讀取文件、請求網(wǎng)絡(luò)數(shù)據(jù)、或者數(shù)據(jù)庫操作等都可以是異步的。
import asyncio async def fetch_data(): print("Fetching data...") await asyncio.sleep(2) # 模擬耗時(shí)的 I/O 操作,如數(shù)據(jù)庫查詢或API請求 return {"data": "sample"}
2.2 使用 await 等待異步操作的完成
通過 await
等待異步任務(wù)的完成,可以避免阻塞程序的執(zhí)行。
async def main(): data = await fetch_data() print(data) # 運(yùn)行事件循環(huán) asyncio.run(main())
2.3 并發(fā)執(zhí)行多個(gè)任務(wù)
通過 asyncio.gather()
,你可以并發(fā)地執(zhí)行多個(gè)異步任務(wù),而不是順序等待每個(gè)任務(wù)完成。gather
可以同時(shí)啟動(dòng)多個(gè)協(xié)程,并行處理 I/O 操作。
import asyncio async def task_1(): await asyncio.sleep(5) return "Task 1 finished" async def task_2(): await asyncio.sleep(5) return "Task 2 finished" async def main(): # 計(jì)算運(yùn)行耗時(shí) start_time = asyncio.get_running_loop().time() results = await asyncio.gather(task_1(), task_2()) print(f"Total time: {asyncio.get_running_loop().time() - start_time}") print(results) asyncio.run(main())
輸出結(jié)果是并行執(zhí)行的,雖然 task_1
和 task_2
各需要5秒,但并行總計(jì)耗時(shí)也是5秒。
2.4 創(chuàng)建并管理任務(wù)
asyncio.create_task()
可以將異步函數(shù)封裝成任務(wù),并且不會(huì)阻塞當(dāng)前執(zhí)行。它允許同時(shí)運(yùn)行多個(gè)任務(wù),并在它們完成后獲取結(jié)果。
import asyncio async def task_1(): await asyncio.sleep(2) return "Task 1 complete" async def task_2(): await asyncio.sleep(1) return "Task 2 complete" async def main(): # 計(jì)算運(yùn)行的時(shí)間 start_time = asyncio.get_running_loop().time() t1 = asyncio.create_task(task_1()) t2 = asyncio.create_task(task_2()) await t1 # 等待任務(wù)1完成 await t2 # 等待任務(wù)2完成 print(asyncio.get_running_loop().time() - start_time) print(t1.result()) print(t2.result()) asyncio.run(main())
輸出結(jié)果是:
2.5 處理異常
在復(fù)雜的異步 I/O 操作中,處理異常非常重要。你可以在 await
和 async
任務(wù)中捕獲異常。
async def risky_task(): await asyncio.sleep(1) raise ValueError("An error occurred!") async def main(): try: await risky_task() except ValueError as e: print(f"Caught exception: {e}") asyncio.run(main())
輸出結(jié)果是:
2.6 超時(shí)控制
異步 I/O 操作中常常需要處理超時(shí)情況??梢酝ㄟ^ asyncio.wait_for()
來實(shí)現(xiàn)超時(shí)控制。
async def long_task(): await asyncio.sleep(5) return "Task finished" async def main(): try: result = await asyncio.wait_for(long_task(), timeout=2) print(result) except asyncio.TimeoutError: print("Task timed out") asyncio.run(main())
輸出結(jié)果是:
3. 處理復(fù)雜的異步 I/O 操作
在更復(fù)雜的場景中,可能需要同時(shí)處理多種類型的 I/O 操作,比如網(wǎng)絡(luò)請求、文件讀寫、數(shù)據(jù)庫查詢等。以下是一個(gè)例子,它展示了如何通過 asyncio
同時(shí)處理不同類型的異步操作。
import asyncio async def fetch_data_from_api(): print("Fetching data from API...") await asyncio.sleep(3) # 模擬 API 請求 return {"api_data": "some api data"} async def read_from_file(): print("Reading data from file...") await asyncio.sleep(2) # 模擬文件讀操作 return "file content" async def write_to_db(data): print(f"Writing {data} to database...") await asyncio.sleep(1) # 模擬數(shù)據(jù)庫寫入操作 return "DB write success" async def main(): # 并發(fā)執(zhí)行 I/O 操作 api_task = asyncio.create_task(fetch_data_from_api()) file_task = asyncio.create_task(read_from_file()) # 等待所有 I/O 操作完成 api_data, file_content = await asyncio.gather(api_task, file_task) # 處理 I/O 操作的結(jié)果 print(f"API Data: {api_data}") print(f"File Content: {file_content}") # 寫入數(shù)據(jù)庫 db_result = await write_to_db(api_data) print(db_result) asyncio.run(main())
輸出結(jié)果是:
4. 使用 async/await 的性能優(yōu)勢
- 避免阻塞:傳統(tǒng)的同步 I/O 操作(如文件讀取、網(wǎng)絡(luò)請求)會(huì)阻塞線程,而
async
/await
允許在等待 I/O 操作時(shí)執(zhí)行其他任務(wù),極大提高了并發(fā)處理的能力。 - 降低線程開銷:相比多線程,多協(xié)程(基于
async
的方式)能夠減少線程上下文切換的開銷,在高并發(fā)場景下更加高效。
5. 總結(jié)
利用 async
和 await
處理異步 I/O 操作時(shí),可以有效地管理任務(wù)的并發(fā)執(zhí)行,并通過 asyncio
提供的工具(如 gather
、create_task
)進(jìn)一步簡化復(fù)雜的異步操作。同時(shí),超時(shí)控制、異常處理等功能也很容易集成到異步 I/O 操作中。
到此這篇關(guān)于Python使用asyncio實(shí)現(xiàn)異步操作的示例的文章就介紹到這了,更多相關(guān)Python asyncio異步操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python中asyncio的多種用法舉例(異步同步)
- Python使用asyncio處理異步編程的代碼示例
- Python使用asyncio包實(shí)現(xiàn)異步編程方式
- Python異步庫asyncio、aiohttp詳解
- python協(xié)程異步IO中asyncio的使用
- Python使用asyncio標(biāo)準(zhǔn)庫對異步IO的支持
- Python協(xié)程異步爬取數(shù)據(jù)(asyncio+aiohttp)實(shí)例
- Python使用asyncio異步時(shí)的常見問題總結(jié)
- Python asyncio異步編程常見問題小結(jié)
- Python asyncio異步編程簡單實(shí)現(xiàn)示例
- Python中asyncio庫實(shí)現(xiàn)異步編程的示例
相關(guān)文章
解鎖Python中神器vars內(nèi)置函數(shù)的使用
vars()函數(shù)是一個(gè)內(nèi)置函數(shù),用于返回對象的__字典__,其中包含對象的__屬性__,本文主要為大家詳細(xì)介紹了vars()函數(shù)的具體使用,需要的小伙伴可以了解下2023-11-11Python warning警告出現(xiàn)的原因及忽略方法
在本篇文章里小編給大家分享的是關(guān)于Python warning警告出現(xiàn)的原因及忽略方法,有需要的朋友們可以學(xué)習(xí)參考下。2020-01-01Python實(shí)現(xiàn)批量將MP3音頻轉(zhuǎn)為WAV格式詳解
這篇文章主要介紹了通過Python實(shí)現(xiàn)將MP3音頻轉(zhuǎn)為WAV格式的方法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Python有一定幫助,感興趣的可以了解一下2021-12-12Pandas中把dataframe轉(zhuǎn)成array的方法
下面小編就為大家分享一篇Pandas中把dataframe轉(zhuǎn)成array的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04如何使用VSCode愉快的寫Python于調(diào)試配置步驟
從我的使用經(jīng)驗(yàn)出發(fā),可以說VSCode用來寫Python真的是再合適不過了,你將體驗(yàn)到絲滑的編程體驗(yàn)和無限擴(kuò)展的可能。而且,如果你的項(xiàng)目是包含多種語言的,比如Web開發(fā),你不必再開多個(gè)編輯器和其他工具,因?yàn)檫@一切都可以在VSCode里完成了2018-04-04Pycharm自帶Git實(shí)現(xiàn)版本管理的方法步驟
這篇文章主要介紹了Pycharm自帶Git實(shí)現(xiàn)版本管理的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Python正則表達(dá)式如何進(jìn)行字符串替換實(shí)例
Python正則表達(dá)式在使用中會(huì)經(jīng)常應(yīng)用到字符串替換的代碼。這篇文章主要介紹了Python正則表達(dá)式如何進(jìn)行字符串替換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-12-12