Python中協(xié)程coroutine適用場景分析
一、協(xié)程和線程的比較及其適用場景
1 共用變量問題
多線程中可能出現(xiàn)多個線程爭搶變量,所以變量需要加鎖;協(xié)程中任一時刻都只有一個線程,所以變量不需要加鎖。
但是協(xié)程雖然不像多線程爭搶變量但仍是和多線程一樣共用變量的,即共用變量在某處改變在另外一處引用時也會發(fā)生改變。
2 協(xié)程的適用場景
從資源角度說,協(xié)程只有一個線程只能使用一個cpu核,所以它適合用于IO密集(包括磁盤IO和網絡IO)函數(shù),并不適用于計算密集函數(shù)。
從事情重復性說,協(xié)程類似多線程,適用于被反復調用的函數(shù)(for或while),也可用于做不同事情的多個函數(shù)。
3 協(xié)程的切換
線程是由操作系統(tǒng)來控制切換的,并不需要我們自己來調度;但協(xié)程在操作系統(tǒng)中表現(xiàn)為一個線程,其調度操作系統(tǒng)無能為力,只得我們自己來實現(xiàn)。
await關鍵字表示該位置阻塞時可讓出cpu執(zhí)行,即切換到下一協(xié)程運行;但追根究底對我們而言好像只有await asyncio.sleep()(另外還有future但這個暫不考慮吧)。
所以各協(xié)程間一定要在某個地方(尤其是循環(huán)內)使用await asyncio.sleep()謙讓給其他協(xié)程,不然如果協(xié)程一直不謙讓那其他協(xié)程,那其他協(xié)程只能等該協(xié)程運行完才能運行了。
二、協(xié)程代碼實現(xiàn)
1 協(xié)程函數(shù)的定義
正常函數(shù)怎么寫就怎么寫,在def前面加上async即可。如:
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
2 協(xié)程函數(shù)的調用
入口函數(shù)使用asyncio.run() 進行調用。如:
import asyncio
async def main():
print(f"started at {time.strftime('%X')}")
print('hello world!')
print(f"finished at {time.strftime('%X')}")
if __name__ == "__main__":
# 入口函數(shù)通過asyncio.run()調用
asyncio.run(main())一般協(xié)程函數(shù)調用時在其前面加上await關鍵字進行調用:
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print(f"started at {time.strftime('%X')}")
# 在前面加上await進行調用
# 這種形式和正常的同步執(zhí)行程序效果上沒什么區(qū)別,仍是執(zhí)行完上一步再執(zhí)行下一步
await say_after(1, 'hello')
await say_after(2, 'world')
print(f"finished at {time.strftime('%X')}")
if __name__ == "__main__":
# 入口函數(shù)通過asyncio.run()調用
asyncio.run(main())最后一種是通過asyncio.create_task()調用一般協(xié)程函數(shù)。
第二種調用方式也是調用一般協(xié)程函數(shù),但是如果只是這么調用的話協(xié)程函數(shù)并沒有什么作用,比如上邊這個函數(shù)耗時仍然和正常的同步版本一樣是3秒。
協(xié)程的意義在正在于asyncio.create_task()調用形式,asyncio.create_task()可以將協(xié)程函數(shù)包裝成任務,多個任務之間可并行執(zhí)行。如下寫法只耗時2秒。
import asyncio
import time
#學習中遇到問題沒人解答?小編創(chuàng)建了一個Python學習交流群:153708845
class TestAsync:
async def say_after(self,delay, what):
await asyncio.sleep(delay)
print(what)
async def main(self):
print(f"started at {time.strftime('%X')}")
task_list = []
# 等價于[1,2]
for i in range(1, 3, 1):
# 步驟一、使用asyncio.create_task()調用協(xié)程函數(shù),封裝成任務
tmp_task = asyncio.create_task(self.say_after(i, 'hello'))
task_list.append(tmp_task)
# 第二步,await任務
for tmp_task in task_list:
await tmp_task
print(f"finished at {time.strftime('%X')}")
if __name__ == "__main__":
obj = TestAsync()
asyncio.run(obj.main())到此這篇關于Python中協(xié)程(coroutine)詳解的文章就介紹到這了,更多相關Python協(xié)程coroutine內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python函數(shù)實現(xiàn)學員管理系統(tǒng)
這篇文章主要為大家詳細介紹了Python函數(shù)實現(xiàn)學員管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07
python使用pycharm環(huán)境調用opencv庫
這篇文章主要介紹了python使用pycharm環(huán)境調用opencv庫,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02

