Python 異步編程 asyncio簡(jiǎn)介及基本用法
1、asyncio是什么
async io(異步輸入輸出)是一種編程模式,它允許程序在等待I/O操作(如文件讀寫、網(wǎng)絡(luò)請(qǐng)求等)完成時(shí)繼續(xù)執(zhí)行其他任務(wù)。通過(guò)這種方式,可以更有效地利用CPU資源和提高程序的響應(yīng)速度,尤其是在處理大量并發(fā)連接或長(zhǎng)時(shí)間運(yùn)行的任務(wù)時(shí)。
asyncio 是 Python 的一個(gè)庫(kù),用于編寫并發(fā)代碼,使用協(xié)程、任務(wù)和 Futures 來(lái)處理 I/O 密集型和高延遲操作
正常的發(fā)送請(qǐng)求,發(fā)送請(qǐng)求后會(huì)等待連接建立和服務(wù)器響應(yīng),這段時(shí)間內(nèi)cpu是空閑的,也無(wú)法切換到其他任務(wù)
asyncio允許當(dāng)執(zhí)行的任務(wù)遇到IO密集型任務(wù)時(shí)(如發(fā)送請(qǐng)求),cpu空閑,將cpu切換到其他任務(wù)上,做其他任務(wù),等請(qǐng)求建立后,可以重新切換回來(lái),繼續(xù)進(jìn)行操作
IO密集型任務(wù)
IO 密集型任務(wù)是指那些大部分時(shí)間都花費(fèi)在輸入/輸出(I/O)操作上的任務(wù)。這些任務(wù)的特點(diǎn)是,CPU 的計(jì)算量相對(duì)較小,而等待 I/O 操作完成的時(shí)間較長(zhǎng)。常見的 IO 密集型任務(wù)包括文件讀寫、網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)查詢等。
例如連接網(wǎng)絡(luò),發(fā)起連接時(shí)需要cpu參與,等待連接過(guò)程是不需要cpu參與,這段時(shí)間,cpu可以空閑下來(lái),進(jìn)行其他操作,等待到連接建立成功后需要傳輸數(shù)據(jù)了cpu再進(jìn)行操作
特征
- 長(zhǎng)時(shí)間等待:大量時(shí)間花在等待外部設(shè)備或服務(wù)的響應(yīng)上。
- 低 CPU 占用:CPU 在等待 I/O 操作完成時(shí)處于空閑狀態(tài),因?yàn)椴恍枰M(jìn)行復(fù)雜的計(jì)算。
2、怎么用
1、基本用法
import asyncio
# 定義一個(gè)異步函數(shù)
async def my_coroutine():
print("開始任務(wù)")
# 模擬一個(gè)耗時(shí)操作
await asyncio.sleep(1) # 等待1秒
print("任務(wù)完成")
# 創(chuàng)建事件循環(huán)
loop = asyncio.get_event_loop()
# 運(yùn)行異步函數(shù)直到完成
loop.run_until_complete(my_coroutine())
# 關(guān)閉事件循環(huán)
loop.close()定義了一個(gè)名為my_coroutine的協(xié)程(coroutine),它會(huì)打印一條開始任務(wù),然后暫停執(zhí)行一段時(shí)間(模擬I/O操作),最后再打印任務(wù)完成。await關(guān)鍵字用于暫停協(xié)程的執(zhí)行,直到等待的操作完成。asyncio.sleep是專門用來(lái)模擬異步等待的函數(shù),在實(shí)際應(yīng)用中,你可能會(huì)替換為真正的異步I/O操作,比如網(wǎng)絡(luò)請(qǐng)求或文件操作。
如果你想要同時(shí)運(yùn)行多個(gè)異步任務(wù),你可以使用asyncio.gather或者asyncio.wait等函數(shù)來(lái)管理這些任務(wù)。
實(shí)際上這樣顯示不出協(xié)程的用途
但是如果有多個(gè)任務(wù)就可以了
import asyncio
# 定義一個(gè)異步函數(shù)
async def my_coroutine1():
print("開始任務(wù)1")
# 模擬一個(gè)耗時(shí)操作
await asyncio.sleep(1) # 等待1秒
print("任務(wù)完成1")
async def my_coroutine2():
print("開始任務(wù)2")
# 模擬一個(gè)耗時(shí)操作
await asyncio.sleep(1) # 等待1秒
print("任務(wù)完成2")
async def main():
results = await asyncio.gather(my_coroutine1(), my_coroutine2())
print(results)
if __name__ == '__main__':
asyncio.run(main())
2、關(guān)鍵字 async
定義:
async關(guān)鍵字用來(lái)聲明一個(gè)函數(shù)為異步函數(shù)(即協(xié)程)。當(dāng)一個(gè)函數(shù)被定義為異步時(shí),它不會(huì)像普通函數(shù)那樣立即執(zhí)行其內(nèi)部代碼,而是返回一個(gè)協(xié)程對(duì)象。這個(gè)協(xié)程對(duì)象可以在事件循環(huán)中調(diào)度執(zhí)行。
async def function_name(parameters):
# 協(xié)程體使用場(chǎng)景:
當(dāng)你需要定義一個(gè)可能會(huì)進(jìn)行長(zhǎng)時(shí)間等待的函數(shù)(如網(wǎng)絡(luò)請(qǐng)求、文件讀寫等),你可以使用async來(lái)標(biāo)記該函數(shù),表明它是一個(gè)異步操作,并且可以通過(guò)await來(lái)暫停它的執(zhí)行直到某些條件滿足。
await
定義:await關(guān)鍵字只能出現(xiàn)在由async定義的函數(shù)內(nèi)部,用于暫停當(dāng)前協(xié)程的執(zhí)行,直到所等待的另一個(gè)協(xié)程或異步操作完成。await后面通常跟的是一個(gè)可等待對(duì)象(如另一個(gè)協(xié)程、Future、Task等)。
語(yǔ)法:
await expression
使用場(chǎng)景:
當(dāng)你在一個(gè)異步函數(shù)內(nèi)需要等待另一個(gè)異步操作的結(jié)果時(shí),你可以使用await來(lái)暫停當(dāng)前函數(shù)的執(zhí)行,讓出CPU資源給其他任務(wù),直到等待的操作完成。
asyncio.run():
這是運(yùn)行頂層協(xié)程的主要方式,適用于Python 3.7+版本。它會(huì)創(chuàng)建一個(gè)新的事件循環(huán)并運(yùn)行傳入的協(xié)程,直到協(xié)程完成。完成后,它會(huì)關(guān)閉事件循環(huán)并返回協(xié)程的結(jié)果。
asyncio.create_task():
用于在事件循環(huán)中并發(fā)啟動(dòng)多個(gè)協(xié)程。它接受一個(gè)協(xié)程作為參數(shù),并返回一個(gè)Task對(duì)象,該對(duì)象代表了正在運(yùn)行的任務(wù)。這有助于管理并發(fā)任務(wù),比如同時(shí)發(fā)起多個(gè)網(wǎng)絡(luò)請(qǐng)求。
import asyncio
async def task1():
print("Task 1 started")
await asyncio.sleep(1)
print("Task 1 completed")
async def task2():
print("Task 2 started")
await asyncio.sleep(2)
print("Task 2 completed")
async def main():
# 創(chuàng)建任務(wù)但不等待它們
task_1 = asyncio.create_task(task1())
task_2 = asyncio.create_task(task2())
# 執(zhí)行其他代碼...
# 等待任務(wù)完成
await task_1
await task_2
# 運(yùn)行主函數(shù)
asyncio.run(main())asyncio.gather():
如果想要并發(fā)地運(yùn)行多個(gè)協(xié)程并且收集所有結(jié)果,可以使用gather。它可以接收多個(gè)協(xié)程作為參數(shù),并返回一個(gè)包含所有協(xié)程返回值的列表。
import asyncio
async def task1():
print("Task 1 started")
await asyncio.sleep(1)
print("Task 1 completed")
return "Result from Task 1"
async def task2():
print("Task 2 started")
await asyncio.sleep(2)
print("Task 2 completed")
return "Result from Task 2"
async def main():
# 使用 gather 同時(shí)運(yùn)行多個(gè)任務(wù)
results = await asyncio.gather(task1(), task2())
print(results)
# 運(yùn)行主函數(shù)
asyncio.run(main())asyncio.wait() 可以用來(lái)等待一組協(xié)程中的任意數(shù)量完成。你可以指定不同的等待條件,如全部完成、任何一個(gè)完成等。
import asyncio
async def task1():
print("Task 1 started")
await asyncio.sleep(1)
print("Task 1 completed")
async def task2():
print("Task 2 started")
await asyncio.sleep(2)
print("Task 2 completed")
async def main():
# 創(chuàng)建任務(wù)列表
tasks = [task1(), task2()]
# 等待所有任務(wù)完成
done, pending = await asyncio.wait(tasks, return_when=asyncio.ALL_COMPLETED)
for future in done:
print(future.result())
# 運(yùn)行主函數(shù)
asyncio.run(main())如果你想按完成順序處理結(jié)果,而不是按照任務(wù)創(chuàng)建的順序,可以使用 asyncio.as_completed()。它返回一個(gè)迭代器,在每個(gè)協(xié)程完成后產(chǎn)生它的Future對(duì)象。
import asyncio
async def task1():
print("Task 1 started")
await asyncio.sleep(1)
print("Task 1 completed")
return "Result from Task 1"
async def task2():
print("Task 2 started")
await asyncio.sleep(2)
print("Task 2 completed")
return "Result from Task 2"
async def main():
# 創(chuàng)建任務(wù)列表
tasks = [task1(), task2()]
# 按完成順序處理結(jié)果
for future in asyncio.as_completed(tasks):
result = await future
print(result)
# 運(yùn)行主函數(shù)
asyncio.run(main())asyncio.gather():適合同時(shí)啟動(dòng)多個(gè)任務(wù),并等待所有任務(wù)完成。asyncio.create_task():用于立即啟動(dòng)任務(wù)并在之后等待它們完成。asyncio.wait():提供靈活的等待條件,例如等待所有或任一任務(wù)完成。asyncio.as_completed():根據(jù)任務(wù)完成的順序來(lái)處理結(jié)果。
到此這篇關(guān)于Python 異步編程 asyncio簡(jiǎn)介及基本用法的文章就介紹到這了,更多相關(guān)Python asyncio內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python命令行交互引導(dǎo)用戶選擇寵物實(shí)現(xiàn)
這篇文章主要為大家介紹了python命令行交互引導(dǎo)用戶選擇寵物實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
python中的匿名函數(shù)及編寫無(wú)參數(shù)decorator詳解
這篇文章主要介紹了python中的匿名函數(shù)及編寫無(wú)參數(shù)decorator詳解,高階函數(shù)可以接收函數(shù)做參數(shù),有些時(shí)候,我們不需要顯式地定義函數(shù),直接傳入匿名函數(shù)更方便,需要的朋友可以參考下2023-12-12
深入理解Python __init_subclass__的使用
本文主要介紹了Python __init_subclass__的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2026-05-05
解決CentOS下ImportError: No module named &a
這篇文章主要介紹了解決CentOS下ImportError: No module named '_sqlite3'的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Python的Tornado框架的異步任務(wù)與AsyncHTTPClient
Tornado的奧義就在于異步處理來(lái)提高單線程的Python程序執(zhí)行性能,這里我們就來(lái)詳解Python的Tornado框架的異步任務(wù)與AsyncHTTPClient,需要的朋友可以參考下2016-06-06
Centos下實(shí)現(xiàn)安裝Python3.6和Python2共存
這篇文章主要介紹了Centos下實(shí)現(xiàn)安裝Python3.6和Python2共存,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Python多進(jìn)程multiprocessing用法實(shí)例分析
這篇文章主要介紹了Python多進(jìn)程multiprocessing用法,結(jié)合實(shí)例形式分析了Python多線程的概念以及進(jìn)程的創(chuàng)建、守護(hù)進(jìn)程、終止、退出進(jìn)程、進(jìn)程間消息傳遞等相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
bat和python批量重命名文件的實(shí)現(xiàn)代碼
這篇文章主要介紹了bat和python批量重命名文件的實(shí)現(xiàn)代碼,需要的朋友可以參考下2016-05-05
Python Pingouin數(shù)據(jù)統(tǒng)計(jì)分析技術(shù)探索
Pingouin庫(kù)基于pandas、scipy和statsmodels,為用戶提供了執(zhí)行常見統(tǒng)計(jì)分析的功能,它支持各種統(tǒng)計(jì)方法和假設(shè)檢驗(yàn),例如 t-tests、ANOVA、correlation analysis 等,本文通過(guò)一些示例代碼,以更全面地了解如何使用Pingouin庫(kù)進(jìn)行統(tǒng)計(jì)分析,2024-01-01

