前面寫的異步編程的幾篇文章:編程
廢話很少說,上代碼:bash
這個代碼只適用於Python3.7,由於
asyncio.run()
在 Python3.7才提出微信
import asyncio
async def heavy_task():
await asyncio.sleep(2)
async def main():
for _ in range(100):
await heavy_task()
if __name__ == '__main__':
asyncio.run(main())
複製代碼
請問上面這個代碼須要多久完成?答案是20秒,而不是咱們指望的那樣在2秒內完成。session
理解緣由須要先搞明白await
到底幹了什麼:事件循環執行到await
的時候,會把當前的協程掛起(暫停),而後看看當前的事件循環池裏面有哪些其餘能夠執行的協程,接着繼續執行其餘的協程。app
main()
中的 for 循環是一個總體,await heavy_task()
會把整個 main()
掛起,等到await的heavy_task()
執行完了(也就是兩秒後),接着再返回main()
,從上次落下的地方繼續。而上次落下的地方,仍是在這個 for 循環裏面的。異步
因此,這個程序是異步的嗎?能夠確定的說是的,針對整個程序是異步的。可是對於main()
,它的for
循環仍是阻塞的。async
上述問題的根源在於:咱們沒能及時往事件循環裏面添加協程。for
循環要等到heavy_task()
結束了再建立下一個協程。要解決這個能夠用asyncio.gather()
:異步編程
前面一篇文章裏面咱們的那個代碼:先把全部的協程事先建立好,而後一次性交給asyncio.gather()
。oop
import time
import asyncio
import aiohttp
async def fetch_async(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
status_code = resp.status
print(status_code)
async def visit_async():
start = time.time()
tasks = []
for _ in range(100):
tasks.append(fetch_async(URL))
await asyncio.gather(*tasks)
end = time.time()
print("visit_async tasks %.2f seconds" % (end - start))
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(visit_async())
複製代碼
若是你像我同樣真正熱愛計算機科學,喜歡研究底層邏輯,歡迎關注個人微信公衆號:post