摘要:并發的方式有多種,多線程,多進程,異步等。多線程和多進程之間的場景切換和通訊代價很高,不適合密集型的場景關于多線程和多進程的特點已經超出本文討論的范疇,有興趣的同學可以自行搜索深入理解。
編程中,我們經常會遇到“并發”這個概念,目的是讓軟件能充分利用硬件資源,提高性能。并發的方式有多種,多線程,多進程,異步IO等。多線程和多進程更多應用于CPU密集型的場景,比如科學計算的時間都耗費在CPU上,利用多核CPU來分擔計算任務。多線程和多進程之間的場景切換和通訊代價很高,不適合IO密集型的場景(關于多線程和多進程的特點已經超出本文討論的范疇,有興趣的同學可以自行搜索深入理解)。而異步IO就是非常適合IO密集型的場景,比如網絡爬蟲和Web服務。
在計算機程序中,IO就是讀寫磁盤、讀寫網絡的操作,這種讀寫速度比讀寫內存、CPU緩存慢得多,前者的耗時是后者的成千上萬倍甚至更多。這就導致,IO密集型的場景99%以上的時間都花費在IO等待的時間上。異步IO就是把CPU從漫長的等待中解放出來的方法。這就可以大大提高我們寫的軟件系統的并發性。這樣的軟件,可以是網絡爬蟲,也可以是Web服務等一切IO密集型的系統。
異步IO的優勢顯而易見,各種語言都通過實現這個機制來提高自身的效率,Python也不例外。Python經歷了2和3兩個大版本的躍遷。這其中也有對異步IO支持的變化歷程。
Python 2的異步IO庫Python 2 時代官方并沒有異步IO的支持,但是有幾個第三方庫通過事件或事件循環(Event Loop)實現了異步IO,它們是:
twisted: 是事件驅動的網絡庫
gevent: greenlet + libevent(后來是libev或libuv)。通過協程(greenlet)和事件循環庫(libev,libuv)實現的gevent使用很廣泛。
tornado: 支持異步IO的web框架。自己實現了IOLOOP。
Python 3 官方的異步IOPython 3.4 加入了asyncio 庫,使得Python有了支持異步IO的官方庫。這個庫,底層是事件循環(EventLoop),上層是協程和任務。asyncio自從3.4 版本加入到最新的 3.7版一直在改進中。
Python 3.4 剛開始的asyncio的協程還是基于生成器的,通過 yield from 語法實現,可以通過裝飾器 @asyncio.coroutine (已過時)裝飾一個函數來定義一個協程。比如:
Python 3.5 引入了兩個新的關鍵字 await 和 async 用來替換 @asyncio.coroutine 和 yield from ,從語言本身來支持異步IO。從而使得異步編程更加簡潔,并和普通的生成器區別開來。
注意: 對基于生成器的協程的支持已棄用,并計劃在 Python 3.10 中移除。所以,寫異步IO程序時只需使用 async 和 await 即可。
Python 3.7 又進行了優化,把API分組為高層級API和低層級API。 我們先看看下面的代碼,發現與上面的有什么不同?
除了用 async 替換 @asyncio.coroutine 和用 await 替換 yield from 外,最大的變化就是關于eventloop的代碼不見了,只有一個 async.run()。這就是 3.7 的改進,把eventloop相關的API歸入到低層級API,新引進run()作為高層級API讓寫應用程序的開發者調用,而不用再關心eventloop。除非你要寫異步庫(比如MySQL異步庫)才會和eventloop打交道。
需要注意的是, async.run() 是3.7版新增加的,處于暫定API狀態。 暫定API,是指被有意排除在標準庫的向后兼容性保證之外的應用編程接口。雖然此類接口通常不會再有重大改變,但只要其被標記為暫定,就可能在核心開發者確定有必要的情況下進行向后不兼容的更改(甚至包括移除該接口)。此種更改并不會隨意進行 — 僅在 API 被加入之前未考慮到的嚴重基礎性缺陷被發現時才可能會這樣做。即便是對暫定 API 來說,向后不兼容的更改也會被視為“最后的解決方案” —— 任何問題被確認時都會盡可能先嘗試找到一種向后兼容的解決方案。這種處理過程允許標準庫持續不斷地演進,不至于被有問題的長期性設計缺陷所困。
從上面關于 asyncio 的發展來看它一直在變化,3.4,3.5,3.6, 3.7 都有很多細節上的變化。當我看到3.7的run()函數時,也發現一年前基于3.6的asnycio寫的爬蟲不那么優雅了。
這種變化,一方面改善了asyncio本身的性能和使用方便程度,但另一方面也增加了我們使用者的學習成本、Python升級帶來的改造的成本。如果你以消極的態度抵制這種變化,可以去學習golang,C++來實現你的程序;如果你以積極的態度迎接這種變化,可以更快的掌握這種變化,并優雅 高效的實現你的程序。
只要你喜歡用Python寫程序解決問題,那么就接受并掌握這種變化吧。其實,那種語言不在變,那種技術不在前進。作為程序員,你只有不斷地學習和前進。
uvloopuvloop是用Cython寫的,基于libuv這個C語言實現的高性能異步I/O庫。asyncio自己的事件循環是用Python寫的,用uvloop替換asyncio自己的事件循環可以是asyncio的速度更快。并且使用相當簡潔:
大家在學python的時候肯定會遇到很多難題,以及對于新技術的追求,這里推薦一下我們的Python學習扣qun:784758214,這里是python學習者聚集地?。⊥瑫r,自己是一名高級python開發工程師,從基礎的python腳本到web開發、爬蟲、django、數據挖掘等,零基礎到項目實戰的資料都有整理。送給每一位python的小伙伴!每日分享一些學習的方法和需要注意的小細節
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/43839.html
摘要:具有以下基本同步原語子進程提供了通過創建和管理子進程的。雖然隊列不是線程安全的,但它們被設計為專門用于代碼。表示異步操作的最終結果。 Python的asyncio是使用 async/await 語法編寫并發代碼的標準庫。通過上一節的講解,我們了解了它不斷變化的發展歷史。到了Python最新穩定版 3.7 這個版本,asyncio又做了比較大的調整,把這個庫的API分為了 高層級API和...
摘要:創建第一個協程推薦使用語法來聲明協程,來編寫異步應用程序。協程兩個緊密相關的概念是協程函數通過定義的函數協程對象調用協程函數返回的對象。它是一個低層級的可等待對象,表示一個異步操作的最終結果。 我們講以Python 3.7 上的asyncio為例講解如何使用Python的異步IO。 showImg(https://segmentfault.com/img/remote/14600000...
摘要:理解迭代對象迭代器生成器后端掘金本文源自作者的一篇博文,原文是,俺寫的這篇文章是按照自己的理解做的參考翻譯。比較的是兩個對象的內容是后端掘金黑魔法之協程異步后端掘金本文為作者原創,轉載請先與作者聯系。 完全理解關鍵字with與上下文管理器 - 掘金如果你有閱讀源碼的習慣,可能會看到一些優秀的代碼經常出現帶有 with 關鍵字的語句,它通常用在什么場景呢?今天就來說說 with 和 上下...
摘要:前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。背后的故事本文是對于年之間世界發生的大事件的詳細介紹,闡述了從提出到角力到流產的前世今生。 前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點;分為新聞熱點、開發教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡迎...
閱讀 1875·2021-09-28 09:36
閱讀 2425·2021-09-08 09:35
閱讀 3066·2019-08-30 15:53
閱讀 1553·2019-08-30 14:08
閱讀 664·2019-08-29 18:40
閱讀 2842·2019-08-29 13:57
閱讀 2701·2019-08-29 13:55
閱讀 680·2019-08-26 13:45