python 異步 I/O

若是你想了解異步編程,那麼必然會涉及出許多相關概念。html

  • 堵塞/非堵塞
  • 同步/異步
  • 多進程/多線程/協程

爲何我要學習這個話,由於我想搞懂異步框架和異步接口的調用。因此,個人學習路線是這樣的:python

1.python異步編程
2.python Web異步框架(tornado/sanic)
3.異步接口調用(aiohttp/httpx)編程

那麼異步編程有什麼好處?在某些場景下它能夠提升性能。咱們知道CPU的速度快於磁盤、網絡等IO。一旦遇到IO操做,如讀寫文件、發送網絡數據時,就須要等待IO操做完成,才能進行下一步操做。這種狀況稱爲同步IO。咱們可使用多線程來解決這類問題,另外一種方式是經過異步。網絡

python在3.4版本引入asyncio,到 3.5版本又加入async/await來簡化異步的使用。多線程

先來舉個簡單的例子,假如,你和女友逛街。你的目的是去看新上市的華爲P40手機,而你女友是去看新款的衣服。大家的逛街流程是這樣的。併發

import time


def clothes_shop():
    print("女友看衣服..")
    time.sleep(8)
    print("...出來了")


def huawei_shop():
    print("體驗手機..")
    time.sleep(5)
    print("...出來了")

print(time.ctime(), "開始逛街")
clothes_shop()
huawei_shop()
print(time.ctime(), "結束.")

運行結果:框架

Thu Apr 16 00:08:22 2020 開始逛街
女友看衣服..
...出來了
體驗手機..
...出來了
Thu Apr 16 00:08:35 2020 結束.

假設單位是分鐘,大家總共耗時13分鐘。異步

接下來,看看用異步是如何處理的:async

import asyncio
import time


async def shop(delay, what):
    print(what)
    await asyncio.sleep(delay)
    print("...出來了")


async def main():
    task1 = asyncio.create_task(shop(8, '女友看衣服..'))
    task2 = asyncio.create_task(shop(5, '體驗手機..'))

    print(time.ctime(), "開始逛街")
    await task1
    await task2
    print(time.ctime(), "結束.")


asyncio.run(main())

經過 async/await 語法進行聲明,是編寫 asyncio 應用的推薦方式。異步編程

  • async 聲明一個函數爲異步函數。
  • await 聲明處理比較耗費時的動做。
  • asyncio.run() 函數用來運行最高層級的入口點 main() 函數。
  • asyncio.create_task() 函數用來併發運行做爲 asyncio 任務 的多個協程。

其實,思路很是簡單,就是你和女友各逛各自的,先出來的等等對方。

嚴重警告!提醒廣大直男,現實生活中千萬不要這麼思考問題。必定要陪女友一塊兒看衣服,還要主動去付錢。

來看看運行結果:

Thu Apr 16 00:19:19 2020 開始逛街
女友看衣服..
體驗手機..
...出來了
...出來了
Thu Apr 16 00:19:27 2020 結束.

假設單位是分鐘,只須要8分鐘搞定。

經過上面的例子,能夠看到 task一、task2仍然有先後順序,這種先後順序的時間能夠忽略不計。可是,咱們也是可使用asyncio.gather()方法併發運行任務。

#……

async def main():
    print(time.ctime(), "開始逛街")
    await asyncio.gather(
        shop(8, '女友看衣服..'),
        shop(5, '體驗手機..')
    )
    print(time.ctime(), "結束.")

asyncio.run(main())

運行結果同上,這裏就再也不貼了。

參考:https://docs.python.org/zh-cn/3/library/asyncio.html

相關文章
相關標籤/搜索