今天我們學異步協程
- 概念
- 第一個案例
- 第二個案例
- 實作異步下載圖片
- 整體的思路流程
- 很黃很暴力
概念
- event_loop:事件回圈,也就是通過不斷的回圈獲取任務的狀態(完成/未完成)來分配任務,
- coroutine:協程物件,python中萬物皆物件,不多說,懂的都懂,
- task:任務物件,對協程物件進行包裝,加上了狀態,完成和未完成,
- future:和task一樣,只不過可以提前包裝,
- async:定義一個協程,定義!
- await:掛起阻塞的操作,還記得之前說的IO等待嗎,在那前面就要用到這個,
第一個案例
第一步,匯入我們的asyncio模塊,async+io!!!

第二步,用async定義一個協程,定義!

記住用await掛起阻塞的操作,也就是asyncio.sleep(2),這里是為了模擬下載所需要花費的時間!
awa
第三步,創建一個協程物件,物件,懂的都懂!

第四步,用event_loop創建一個事件回圈,也就是游戲里的任務公布欄之類的~

第五步,是不是覺得該把任務物件方法事件回圈中了??還真是的!

然后執行,就會成功執行我們的async函式:

第二個案例
那么這個時候就要有人問了,剛開始說的1,2,5,6都用上了,那3,4呢,3,4呢,3,4呢……
這就給大家用上!
task

這里我們就把duixiang這個協程物件放置到task任務物件,然后再把task任務物件放到任務串列中:

那么到這里就有人問了,用task和不用task又沒有區別,為什么要用task呢?
我們來列印一下任務完成前后的task!

看到沒有!!task給每個任務都貼上了標簽,讓回圈器更好的去篩選哪些是完成了的,哪些是沒完成的!
future也是一樣的,這里就不多說了,我們主要用task,
實作異步下載圖片
昨天呢,我們本來是要用異步實作下載圖片的,但是遇到了一個小問題,那就是requests模塊它不支持異步,那我們也沒有辦法強人鎖男的啦,人各有志,讓我們工地見面,
好啦,教大家一個支持異步的同時也支持requests功能的新模塊!
aiohttp aiohttp aiohttp aiohttp aiohttp ……
aiohttp
首先,環境安裝!
pip install aiohttp
當然你也可以在pycharm里直接搜索安裝模塊!
安裝完了這個模塊之后呢,先不要急,先想一個問題:
我們既然有了行程池,又有了異步,是不是可以把他們結合起來呢?是的!!
所以就有一個東西,叫做多執行緒異步協程,也就是說每個執行緒里的程式都能進行異步!!! 如果還是聽不懂的話…那就照著用,畢竟用起來也是不難的,因為異步協程這一部分知識呢,是屬于基礎進階那一塊的,想要詳細說又要花很多篇幅,如果你實在是想學,或者實在是對基礎不太熟練,那就留個言,如果反映人數夠多的話,小澤就專門開一個基礎的坑,帶大家一起學python的基礎!
但是先告訴大家有這個東西,今天呢,我們還是只來實作多任務異步協程,而不是多執行緒異步協程!
整體的思路流程
我們已經有了aiohttp,心里就會很踏實也很安心,所以先按照流程來,這次跟著小澤的思路走:
第一步,我們先寫一個下載圖片的函式:
# 定義一個函式,需要傳入url引數
def func(url):
# UA偽裝
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
}
# 向圖片的網址發起請求,獲取二進制資料
response = requests.get(url=url,headers=headers).content
# 用背景關系管理器保存
name = url.split('/')[-1]
with open(name,'wb') as fp:
fp.write(response)
路人:你明明說了requests不能用,你還用,你是不是傻!
害,這里不就是用一下嘛,方便我們思路的繼續進行,聽懂掌聲~
第二步,找到我們的三張圖片,如果你比較懶,你肯定很懶,那就用小澤給大家準備的三張圖片好了:
urls = ['https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_01.png',
'https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_02.png',
'https://ziyuan.jumpw.com/heroactivity/cases2020/anniversary/images/img_03.png'
]
放心,不是什么美女 美麗的圖片,只是一些正常的圖片~
第三步,建立一個回圈,把urls里的url依次放入函式中……
等等!這樣不就成了同步的操作,說好的多任務異步協程呢!
所以真正的第三步是用回圈把所有任務都封裝起來:
# 建立任務串列
tasks = []
# 遍歷出每一個url
for url in urls:
# 協程物件
a = func(url)
# 封裝
task = asyncio.ensure_future(a)
# 把封裝好的任務加到任務串列里
tasks.append(task)
當然,也不要忘了給我們的函式,加上async,這樣才能讓系統知道這個函式是個協程函式!

然后接下來,就是建立事件回圈,再把我們的任務串列放進事件回圈中!
# 建立事件回圈
loop = asyncio.get_event_loop()
# 把任務串列放到事件回圈中
loop.run_until_complete(asyncio.wait(tasks))
因為是任務串列,而不是單個任務,所以前面要加上asyncio.wait() 不加的統統拉出去,這么囂張還想開軍艦!
好的,整段寫完,剩下的唯一一個問題就是requests模塊的問題啦,現在我們就開始說,到底要怎么用aiohttp~
直接上代碼!
async def func(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
}
# 方便我們直觀看到異步的效果
print('開始下載',url)
# 類似于背景關系管理器,就是with open,with前面一定要加async,固定寫法
# as session是類似起名字一樣
async with aiohttp.ClientSession() as session:
# async with跟上面同理,await是手動掛起,因為向圖片發起請求是IO操作
async with await session.get(url=url,headers=headers) as response:
# 同樣的,對回傳的資料進行決議也是IO操作
# 不同于requests模塊,read()指的是決議二進制資料
# text() 就是我們平時用的text
# 而json物件則要用json()
data = await response.read()
# 對url最后的部分進行截取
name = url.split('/')[-1]
with open(name,'wb') as fp:
fp.write(data)
print('下載完成',url)
我們只需要把func這個協程物件,改成如上所述的內容就可以啦!
至于為什么呢,用法就是上面那樣用的,如果看代碼看不懂的話…可能是前面幾章你沒有好好看,當然如果真的真的看不懂,不要怕,先能看懂多少看懂多少,更詳細的我們之后再說,在評論區留下你的疑惑和想跟小澤說的話,么么噠~
然后直接運行,揍你!

看著下載效率,多棒啊,我好了,你們呢~
關于多任務異步協程呢,就先到這里了,更詳細的要放到不知道哪一篇講了,因為很多小伙伴在催著要講模擬登陸這一塊了……
很黃很暴力

沒廣告,沒賣課,只有一群愛學習的小伙伴,如果你基礎薄弱,或者想搞些大的,歡迎加進來!!!
小澤愛你們,(づ ̄ 3 ̄)づ
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/232470.html
標籤:python
