前言
為了簡化并更好地標識異步IO,從Python 3.5開始引入了新的語法async和await,可以讓coroutine的代碼更簡潔易讀。
請注意,async和await是針對coroutine的新語法,要使用新的語法,只需要做兩步簡單的替換:
把@asyncio.rotoutine替換為async; 把yield from替換為await。async/await 是一種異步變成方法,還有兩種你可能聽過,
1. 回調
2. Promise
(寫過 JavaScript 的肯定很熟悉了)
異步意味著任務不會阻塞,比如,如果我要下載一個比較忙的網絡資源,我的程序不需要一直等待下載完成,它可以在等待下載時繼續做其他事情。這與并行執行多個操作不同。以下偽代碼比較容易理解:
# 慢方法page = get_page_sync('some_page')# 會阻塞整個程序的運行print(page)
有兩種方法可以改善上述的情況
(一)首先,讓我們試試使用線程。通過使用線程,我們可以將 get_page_sync 調用放到單獨的線程去執行,這樣主線程 就可以繼續執行其他操作。
# 將慢方法放到單獨的線程執行t = threading.thread( target = get_page_sync('some_page',args=('some_page',)))t.run()# 在線程運行時執行其他操作do_something_else()# 等待線程完執行成t.join()
線程有幾個優缺點,主要的缺點是:
1. 必須在改變共享數據前鎖定共享數據
2. 只能通過傳遞給主線程消息來處理線程內的異常
(二)現在我們試試第二種中的 async/await,Python3.5 開始支持的 async/await 方式,與第一種(線程)之間的主要區別在于,后者是操作系統內核執行上下文切換,而前者中我們自己控制。(上下文切換即,當多個線程正在運行時,內核可能停止當前進程,使其進入休眠狀態,并選擇不同的線程繼續執行。這被稱作搶占式多任務處理【Preemption】)
當我們自己控制時,它被稱作非搶占式或合作型多任務式,因為是我們自己處理上下文切換,所以我們需要一個調度程序,也叫做『事件循環』。此事件循環只循環遍歷等待中的調度,并運行它的所有事件。每當我們產生操作時,當前任務會被添加到隊列中,且第一個任務(優先級而非順序)從隊列中彈出并開始執行。例如,可以通過以下方式更改上述偽代碼:
async def print_page(): page = await get_page_sync('some_page') print(page)
當我們觸發上面的語句時,get_page_async 方法將非阻塞的獲取 some_page 還有 yield 句柄,這意味著我們的 print_page 函數將控制時間循環 ,并且時間循環可以繼續執行其他曹組,知道我們得到返回的響應。
新聞熱點
疑難解答