Python 非同步教程:Asyncio
原文:http://djangostars.com/blog/asynchronous-programming-in-python-asyncio/
譯文:開源中國
如果你已經決定要理解 Python 的非同步部分,歡迎來到我們的"Asyncio How-to "。
註:哪怕連非同步範式的存在都不知道的情況下,你也可以成功地使用 Python。但是,如果你對底層運行模式感興趣的話,asyncio 絕對值得查看。
非同步是怎麼一回事?
在傳統的順序編程中, 所有發送給解釋器的指令會一條條被執行。此類代碼的輸出容易顯現和預測。 但是…
譬如說你有一個腳本向 3 個不同伺服器請求數據。 有時,誰知什麼原因,發送給其中一個伺服器的請求可能意外地執行了很長時間。想像一下從第二個伺服器獲取數據用了 10 秒鐘。在你等待的時候,整個腳本實際上什麼也沒幹。如果你可以寫一個腳本可以不去等待第二個請求而是僅僅跳過它,然後開始執行第三個請求,然後回到第二個請求,執行之前離開的位置會怎麼樣呢。就是這樣。你通過切換任務最小化了空轉時間。儘管如此,當你需要一個幾乎沒有 I/O 的簡單腳本時,你不想用非同步代碼。
還有一件重要的事情要提,所有代碼在一個線程中運行。所以如果你想讓程序的一部分在後台執行同時干一些其他事情,那是不可能的。
準備開始
這是 asyncio 主概念最基本的定義:
協程— 消費數據的生成器,但是不生成數據。Python 2.5 介紹了一種新的語法讓發送數據到生成器成為可能。我推薦查閱 David Beazley "A Curious Course on Coroutines and Concurrency" 關於協程的詳細介紹。
任務— 協程調度器。如果你觀察下面的代碼,你會發現它只是讓 eventloop 儘快調用它的step ,同時 _step 只是調用協程的下一步。
事件循環— 把它想成 asyncio 的中心執行器。
現在我們看一下所有這些如何融為一體。正如我之前提到的,非同步代碼在一個線程中運行。
從上圖可知:
1.消息循環是在線程中執行
2.從隊列中取得任務
3.每個任務在協程中執行下一步動作
4.如果在一個協程中調用另一個協程(await),會觸發上下文切換,掛起當前協程,並保存現場環境(變數,狀態),然後載入被調用協程
5.如果協程的執行到阻塞部分(阻塞 I/O,Sleep),當前協程會掛起,並將控制權返回到線程的消息循環中,然後消息循環繼續從隊列中執行下一個任務...以此類推
6.隊列中的所有任務執行完畢後,消息循環返回第一個任務
非同步和同步的代碼對比
現在我們實際驗證非同步模式的切實有效,我會比較兩段 python 腳本,這兩個腳本除了_sleep _方法外,其餘部分完全相同。在第一個腳本里,我會用標準的 time.sleep 方法,在第二個腳本里使用 asyncio.sleep 的非同步方法。
這裡使用 Sleep 是因為它是一個用來展示非同步方法如何操作 I/O 的最簡單辦法。
使用同步 sleep 方法的代碼:
腳本輸出:
使用非同步 Sleep 的代碼:
腳本輸出:
從輸出可以看到,非同步模式的代碼執行速度快了大概兩秒。當使用非同步模式的時候(每次調用 await asyncio.sleep(1) ),進程式控制制權會返回到主程序的消息循環里,並開始運行隊列的其他任務(任務A或者任務B)。
當使用標準的 sleep 方法時,當前線程會掛起等待。什麼也不會做。實際上,標準的 sleep 過程中,當前線程也會返回一個 python 的解釋器,可以操作現有的其他線程,但這是另一個話題了。
推薦使用非同步模式編程的幾個理由
很多公司的產品都廣泛的使用了非同步模式,如 Facebook 旗下著名的 React Native 和 RocksDB 。像 Twitter 每天可以承載 50 億的用戶訪問,靠的也是非同步模式編程。所以說,通過代碼重構,或者改變模式方法,就能讓系統工作的更快,為什麼不去試一下呢?
題圖:pexels,CC0 授權。
點擊展開全文
※如何正確閱讀計算機科學書籍?
※如何寫出優雅的 Docstring?
※一步一步搭建視頻聚合網站
※深入理解子進程
※深入理解子進程:Python 相關源碼解析
TAG:編程派 |
※Python非同步Web編程
※Python 標準庫之 collections 使用教程
※Python鏈式操作:PyFunctional
※Python之Sklearn使用教程
※基於Asyncio的Python微框架:Quart
※Python之tworoutine
※為什麼Python如此火?Why Python is so popular?
※Bayesian Personalized Ranking 演算法解析及Python實現
※Python中使用Type hinting 和 annotations
※Process-Forest-Window進程日誌分析工具;python版的BloodHound
※Python async/await 介紹
※Python爬蟲學習Scrapy之Spiders
※Python 標準庫精華: collections.Counter
※在Python中使用Elasticsearch
※如何 Docker 化 Python Django 應用程序
※用Python彈鋼琴:mingus
※對 Python 開發者而言,IPython 仍然是 Jupyter Notebook 的核心
※Python 繪圖庫 Matplotlib 入門教程
※Logistic regression 的梯度下降解法-附python實現
※python介面測試之token&session的處理