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