Python3协程(coroutine)理解
一、背影說明
最早開始接解協程應該是看到requests庫代碼里有await的字眼,接下來曾多次嘗試理解協程怎么用,但都失敗了。
主要的問題是很多文章上來就是告訴你生成器是什么、原理是什么,我一直覺得原理這東西深入理解時是應該的,但是我作為一個小白我不希望你跟我講原理,我沒耐心也聽不懂。
我只希望你告訴我協程有什么用效果是什么、我該怎么調用。
今天又去看了一下,有些理解,但不一定準確,為了下次不重頭再來,暫且先記一記。
二、協程代碼實現
2.1 協程函數的定義
正常函數怎么寫就怎么寫,在def前面加上async即可。如:
async def say_after(delay, what):await asyncio.sleep(delay)print(what)2.2 協程函數的調用
入口函數使用asyncio.run() 進行調用。如:
import asyncioasync def main():print(f"started at {time.strftime('%X')}")print('hello world!')print(f"finished at {time.strftime('%X')}")if __name__ == "__main__":# 入口函數通過asyncio.run()調用asyncio.run(main())一般協程函數調用時在其前面加上await關鍵字進行調用:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' import asyncio import timeasync def say_after(delay, what):await asyncio.sleep(delay)print(what)async def main():print(f"started at {time.strftime('%X')}")# 在前面加上await進行調用# 這種形式和正常的同步執行程序效果上沒什么區別,仍是執行完上一步再執行下一步await say_after(1, 'hello')await say_after(2, 'world')print(f"finished at {time.strftime('%X')}")if __name__ == "__main__":# 入口函數通過asyncio.run()調用asyncio.run(main())最后一種是通過asyncio.create_task()調用一般協程函數。
第二種調用方式也是調用一般協程函數,但是如果只是這么調用的話協程函數并沒有什么作用,比如上邊這個函數耗時仍然和正常的同步版本一樣是3秒。
協程的意義在正在于asyncio.create_task()調用形式,asyncio.create_task()可以將協程函數包裝成任務,多個任務之間可并行執行。如下寫法只耗時2秒。
import asyncio import timeasync def say_after(delay, what):await asyncio.sleep(delay)print(what)async def main():print(f"started at {time.strftime('%X')}")task_list = []for i in range(2):# 步驟一、使用asyncio.create_task()調用協程函數,封裝成任務tmp_task = asyncio.create_task(say_after(i, 'hello'))task_list.append(tmp_task)# 第二步,await任務for tmp_task in task_list:await tmp_taskprint(f"finished at {time.strftime('%X')}")if __name__ == "__main__":asyncio.run(main())三、協程和線程的比較及其適用場景
3.1 共用變量問題
多線程中可能出現多個線程爭搶變量,所以變量需要加鎖;協程中任一時刻都只有一個線程,所以變量不需要加鎖。
但是協程雖然不像多線程爭搶變量但仍是和多線程一樣共用變量的,即共用變量在某處改變在另外一處引用時也會發生改變。
3.2 協程的適用場景
從資源角度說,協程只有一個線程只能使用一個cpu核,所以它適合用于IO密集(包括磁盤IO和網絡IO)函數,并不適用于計算密集函數。
從事情重復性說,協程類似多線程,適用于被反復調用的函數(for或while),也可用于做不同事情的多個函數。
3.3 協程原理
await關鍵字表示該位置阻塞時可讓出cpu執行;阻塞一般是sleep和IO阻塞(包括磁盤IO和網絡IO),但我不確定IO阻塞能不能自動讓出來還是得寫專門的方法。
總結
以上是生活随笔為你收集整理的Python3协程(coroutine)理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python基础教程:数据结构
- 下一篇: Python3压缩和解压缩实现