●在介紹Python的一些強大特性時,人們常常編造一些示例,以孤立的示例解釋各種特性。通過設計并構建真實的應用程序,從設計原型一直演示到開發(fā)出符合生產質量要求的應用程序,整個過程不只讓你了解各種特性如何工作,還會讓你看到它們如何作為更大的系統(tǒng)設計過程的組成部分集成起來。另外,本書還會提供一些有用的注意項,并推薦一些庫,這些內容是Python大會問答環(huán)節(jié)的主要關注點。本書還會討論現(xiàn)代Python開發(fā)的實踐和技術,幫助你編寫清晰的、易于維護的代碼。
●本書針對的是已經能夠使用Python編寫簡單程序但想要理解什么時候適合使用高級特性的開發(fā)人員,讓他們能夠自如地使用這些高級特性。想要提升自身Python編程水平以及已經具有豐富的經驗但希望了解新版本Python特性的開發(fā)人員,都特別適合閱讀本書。
【本書內容】
本書精心挑選了主題,旨在介紹Python編程的各個不同方面。Python社區(qū)作為一個整體沒有充分理解或者利用這些方面,而且在指導新人時,不會把它們理所當然地教給新人。這并不是說這些特性一定很復雜,或者很難理解(當然有些特性確實如此),我相信,所有程序員都應該熟悉這些特性,即使他們并不會用到這些特性。
●第1章將介紹使用Python編寫簡單程序的不同方式,還會介紹Jupyter記事本以及Python調試器的用法。雖然這兩者都是相對來說為人熟知的工具,但很多人只熟悉其中的一個工具,而不是兩者都能夠熟練使用。本章還會介紹編寫命令行接口的不同方式,以及一些有用的第三方庫,它們支持簡潔的命令行工具開發(fā)。
●第2章將介紹幫助識別代碼中的錯誤的工具,例如自動測試和linting工具。無論是編寫大型代碼庫、很少需要編輯的代碼庫,還是要吸收第三方貢獻的代碼庫,這些工具都能夠讓你更容易地寫出讓自己有信心的代碼。這里介紹的工具都是我推薦的工具,但是,本章的關注點是理解它們的優(yōu)缺點。你可能已經使用過其中的一個或多個工具,并且對于是否適合使用它們有自己的觀點。本章將幫助你理解權衡點,從而做出明智的決定。
●第3章將介紹Python中的代碼打包和依賴項分發(fā)。對于編寫可分發(fā)給其他人的應用程序,以及設計能夠可靠工作的部署系統(tǒng)來說,這些都是重要的功能。我們將使用這些功能,把獨立的腳本轉換為可安裝的應用程序。
●第4章將介紹插件架構。這是一種強大的功能。經?梢钥吹綄W習插件架構的人使用它,這導致講解Python的人們對于是否講解插件架構持謹慎態(tài)度。對于我們的示例,插件架構十分適用。本章還將介紹一些用于命令行工具的高級技術,它們能夠讓調試基于插件的系統(tǒng)變得更加容易。
●第5章將介紹Web接口和編寫復雜函數(shù)的技術,如裝飾器和閉包。這些技術在Python中已經是習語,但在其他許多編程語言中很難表達。本章還將介紹如何恰當?shù)厥褂贸橄蠡。人們常常不建議使用抽象基類,因為學習抽象基類的人傾向于到處使用它們。在特定場景中,有節(jié)制地使用抽象基類是有優(yōu)勢的,當把抽象基類與第2章介紹的一些工具結合使用時更是如此。
●第6章將用另一個重要組件擴展我們的示例,這個組件就是收集數(shù)據的聚合服務器。本章還將演示Python程序員會用到的一些重要的第三方庫,例如requests庫。
●第7章將介紹Python中的線程和異步編程。線程常常會導致難以探查的bug。異步代碼能夠用于類似的任務,但許多Python程序員還沒有使用過這種習語,因為使用異步編程時,程序的行為與同步編程有很大區(qū)別。本章重點討論在真實場景中如何使用并發(fā)來實現(xiàn)某個結果,而不只是演示一個簡單的示例,或者演示異步編程的局限性。本章旨在得到能夠在真實場景中使用的代碼,并讓你徹底理解權衡點,而不是進行獨立的技術演示。
●第8章將更加深入地介紹異步編程,講解異步代碼的測試以及一些第三方庫。使用這些庫能夠編寫在異步上下文中處理外部工具(如數(shù)據庫)的代碼。本章還將簡要地介紹一些可以用來編寫出色API的高級技術,例如上下文管理器和上下文變量,它們對于異步編程很有幫助。
●第9章返回Jupyter,使用它的一些功能來實現(xiàn)數(shù)據可視化和方便的用戶交互。我們將介紹如何在Jupyter記事本中把異步代碼用于小部件,還將介紹迭代器的高級用法和實現(xiàn)復雜數(shù)據類型的多種方式。
●第10章將詳細介紹如何讓Python代碼運行得更快,如何使用不同類型的緩存,以及這些緩存適用的場景。本章還將介紹如何對應用程序中的各個Python函數(shù)進行基準測試,以及如何解讀結果以找出速度緩慢的原因。
●第11章將擴展本書前面介紹過的一些概念,以更加優(yōu)雅地處理錯誤。我們將介紹如何修改插件架構,以便無縫地處理錯誤,同時保留完整的向后兼容性,還將深入介紹如何設計在遇到錯誤時就處理錯誤的過程。
●第12章將使用Python的迭代器和協(xié)程來增強我們開發(fā)的儀表板,為它們添加一些功能,這些功能不是實現(xiàn)被動的數(shù)據收集,而是主動檢查收集到的數(shù)據,從而允許我們構建包含多個步驟的分析流。
●本書按照構建一個真實軟件的順序,通過一個貫穿全書的示例,解釋其他教程中一般不會講解的各種Python語言特性:從利用入口點讓可重用的控制臺腳本成為微服務,一直到高效使用asyncio整理來自多個數(shù)據源的數(shù)據。在此過程中,本書將介紹基于類型提示的linting、低開銷的測試,以及其他自動執(zhí)行的質量檢查,以演示真實的開發(fā)過程。
●通過閱讀本書,你將了解以下內容:
Python異步編程。
插件架構。
如何使用類型注解。
Python相關測試技術。
打包和依賴項管理。
●具體而言:
第1章和第2章介紹開發(fā)環(huán)境和相關的工具;
第3~6章涵蓋代碼打包和依賴項分發(fā)、插件架構、接口、聚合服務器等實用內容;
第7章與第8章討論線程和異步編程相關內容,以及一些高級主題;
第9~12章涉及可視化、調優(yōu)、錯誤處理以及數(shù)據分析相關主題。
●本書提供示例代碼下載,讀者可訪問本書GitHub頁面https://github.com/MatthewWilkes/advanced-python-development.git,簽出Git存儲庫并按照本書內容一步步學習。
Python是一門非常成功的編程語言,自問世以來的30多年間,得到了非常廣泛的應用。主流操作系統(tǒng)默認提供Python,世界上的一些大型網站使用Python開發(fā)后臺,科學家常使用Python來拓展新知識。因為這么多人每天都在使用Python,所以Python的改進會快速、大量地出現(xiàn)。并不是每個Python開發(fā)人員都有機會參加會議,或者有時間關注社區(qū)不同部分所做的工作,所以Python語言及其生態(tài)系統(tǒng)的一些功能難免沒有得到它們應得的關注。
本書的目標是介紹Python語言及其工具中并不是每個人都知道的部分。如果你是一名經驗豐富的開發(fā)人員,則很可能已經知道了本書要介紹的許多工具,但可能也有很多是你想要使用卻沒有時間了解的工具。如果你負責維護一個已建成的穩(wěn)定系統(tǒng),就更可能遇到這種情況,因為對于這樣的系統(tǒng),無法頻繁地通過重構組件來利用新的語言特性。
如果你使用Python的時間較短,則可能更加熟悉該語言近期新增的特性,但不會很熟悉廣闊生態(tài)系統(tǒng)中的一些可用的庫。參加一些活動(如Python會議)的一大好處是有機會注意到其他程序員帶來的質量改進,并把它們集成到自己的工作流中。
本書并不是一本用獨立小節(jié)介紹Python不同特性的參考書。相反,本書是按照構建一個真實軟件的方式來組織各個章節(jié)的。
許多技術文檔傾向于提供簡單的示例。簡單的示例很適合解釋某個特性的工作方式,但是對于理解什么時候使用這種特性沒有太大幫助。而且,也很難把簡單的示例作為基礎來構建軟件,因為復雜代碼的架構方式與簡單代碼有很大的區(qū)別。
通過使用這個示例,我們能夠在具體的上下文中思考技術選擇。你將了解在判斷某個方法是否合適時,需要記住哪些考慮因素。使用方式彼此相關的主題將被放到一起進行介紹,而不是把工作方式相關的主題放到一起進行介紹。
【關于本書】
我撰寫本書的目的,是分享我從社區(qū)不同地方學到的知識,以及我在超過15年的時間中編寫Python代碼所積累的經驗。本書可以幫助你利用核心語言和增件庫來提高生產效率。你將學習如何使用異步編程、打包和測試等語言特性來成為一名高效的程序員,盡管嚴格來說,作為一名程序員,并非必須使用它們。
但是,本書的目標讀者是那些想要編寫代碼的人,而不是想要理解深層原理的人。我不會深入介紹涉及Python實現(xiàn)細節(jié)的主題。你不需要grokPython C擴展、元類或算法,就可以通過閱讀本書獲益。
重要的代碼示例用編號的代碼清單展示,本書配套代碼包含這些代碼清單的電子版。其中一些代碼清單下面還直接顯示了輸出,而不是用編號圖的方式單獨顯示輸出。
在本書的配套代碼中,還可以找到示例項目的代碼庫的完整版本,以及幫助完成練習的代碼?偟膩碚f,我建議你從https://github.com/Apress/advanced-python-development簽出Git存儲庫,然后切換到你正在閱讀的章節(jié)的相關分支,一步步學習代碼。
除了代碼清單,本書還展示了一些控制臺會話。當格式上類似于代碼的行以>開頭時,說明顯示的是一個shell會話。這些部分包括需要從操作系統(tǒng)的終端運行的命令。包含>>>的行演示的是Python控制臺會話,應該從Python解釋器運行。
【本書內容】
本書精心挑選了主題,旨在介紹Python編程的各個不同方面。Python社區(qū)作為一個整體沒有充分理解或者利用這些方面,而且在指導新人時,不會把它們理所當然地教給新人。這并不是說這些特性一定很復雜,或者很難理解(當然有些特性確實如此),我相信,所有程序員都應該熟悉這些特性,即使他們并不會用到這些特性。
●第1章將介紹使用Python編寫簡單程序的不同方式,還會介紹Jupyter記事本以及Python調試器的用法。雖然這兩者都是相對來說為人熟知的工具,但很多人只熟悉其中的一個工具,而不是兩者都能夠熟練使用。本章還會介紹編寫命令行接口的不同方式,以及一些有用的第三方庫,它們支持簡潔的命令行工具開發(fā)。
●第2章將介紹幫助識別代碼中的錯誤的工具,例如自動測試和linting工具。無論是編寫大型代碼庫、很少需要編輯的代碼庫,還是要吸收第三方貢獻的代碼庫,這些工具都能夠讓你更容易地寫出讓自己有信心的代碼。這里介紹的工具都是我推薦的工具,但是,本章的關注點是理解它們的優(yōu)缺點。你可能已經使用過其中的一個或多個工具,并且對于是否適合使用它們有自己的觀點。本章將幫助你理解權衡點,從而做出明智的決定。
●第3章將介紹Python中的代碼打包和依賴項分發(fā)。對于編寫可分發(fā)給其他人的應用程序,以及設計能夠可靠工作的部署系統(tǒng)來說,這些都是重要的功能。我們將使用這些功能,把獨立的腳本轉換為可安裝的應用程序。
●第4章將介紹插件架構。這是一種強大的功能。經?梢钥吹綄W習插件架構的人使用它,這導致講解Python的人們對于是否講解插件架構持謹慎態(tài)度。對于我們的示例,插件架構十分適用。本章還將介紹一些用于命令行工具的高級技術,它們能夠讓調試基于插件的系統(tǒng)變得更加容易。
●第5章將介紹Web接口和編寫復雜函數(shù)的技術,如裝飾器和閉包。這些技術在Python中已經是習語,但在其他許多編程語言中很難表達。本章還將介紹如何恰當?shù)厥褂贸橄蠡悺H藗兂32唤ㄗh使用抽象基類,因為學習抽象基類的人傾向于到處使用它們。在特定場景中,有節(jié)制地使用抽象基類是有優(yōu)勢的,當把抽象基類與第2章介紹的一些工具結合使用時更是如此。
●第6章將用另一個重要組件擴展我們的示例,這個組件就是收集數(shù)據的聚合服務器。本章還將演示Python程序員會用到的一些重要的第三方庫,例如requests庫。
●第7章將介紹Python中的線程和異步編程。線程常常會導致難以探查的bug。異步代碼能夠用于類似的任務,但許多Python程序員還沒有使用過這種習語,因為使用異步編程時,程序的行為與同步編程有很大區(qū)別。本章重點討論在真實場景中如何使用并發(fā)來實現(xiàn)某個結果,而不只是演示一個簡單的示例,或者演示異步編程的局限性。本章旨在得到能夠在真實場景中使用的代碼,并讓你徹底理解權衡點,而不是進行獨立的技術演示。
●第8章將更加深入地介紹異步編程,講解異步代碼的測試以及一些第三方庫。使用這些庫能夠編寫在異步上下文中處理外部工具(如數(shù)據庫)的代碼。本章還將簡要地介紹一些可以用來編寫出色API的高級技術,例如上下文管理器和上下文變量,它們對于異步編程很有幫助。
●第9章返回Jupyter,使用它的一些功能來實現(xiàn)數(shù)據可視化和方便的用戶交互。我們將介紹如何在Jupyter記事本中把異步代碼用于小部件,還將介紹迭代器的高級用法和實現(xiàn)復雜數(shù)據類型的多種方式。
●第10章將詳細介紹如何讓Python代碼運行得更快,如何使用不同類型的緩存,以及這些緩存適用的場景。本章還將介紹如何對應用程序中的各個Python函數(shù)進行基準測試,以及如何解讀結果以找出速度緩慢的原因。
●第11章將擴展本書前面介紹過的一些概念,以更加優(yōu)雅地處理錯誤。我們將介紹如何修改插件架構,以便無縫地處理錯誤,同時保留完整的向后兼容性,還將深入介紹如何設計在遇到錯誤時就處理錯誤的過程。
●第12章將使用Python的迭代器和協(xié)程來增強我們開發(fā)的儀表板,為它們添加一些功能,這些功能不是實現(xiàn)被動的數(shù)據收集,而是主動檢查收集到的數(shù)據,從而允許我們構建包含多個步驟的分析流。
【Python版本說明】
在撰寫本書時,Python的版本是Python 3.8,所以本書中的示例是用Python 3.8和Python 3.9的首批開發(fā)版本測試的。不建議使用更老的版本。本書中有極少數(shù)代碼示例不能在Python 3.7或Python 3.6中正常運行。
要學習本書內容,你需要安裝Python pip。在安裝了Python后,系統(tǒng)中就應該已經安裝了pip。有些操作系統(tǒng)故意在Python的默認安裝中去掉了pip,此時,你需要使用操作系統(tǒng)的包管理器自己安裝。這在基于Debian的系統(tǒng)中很常見,此時使用sudo apt install python3-pip就可以安裝pip。在其他操作系統(tǒng)中,可以使用python -m ensurepip --upgrade來讓Python找到pip的版本,或找到特定于你的操作系統(tǒng)的指令。
本書網站(https://github.com/MatthewWilkes/advanced-python-development)提供了代碼示例(也可訪問華章圖書官網http://www.hzbook.com,通過注冊并登錄個人賬號下載)和勘誤表的電子版。如果在學習本書的過程中遇到任何問題,應該首先訪問這些代碼示例和勘誤表。
馬修-威爾克斯
(Matthew Wilkes)
一名經驗豐富的開發(fā)人員,他使用Python開發(fā)Web項目已經有15年了。除了開發(fā)軟件外,他還長期為Python開發(fā)人員提供指導,積極推動開源軟件的發(fā)展,并為許多流行的框架提交過代碼。他對開源軟件的貢獻主要集中在數(shù)據庫的細節(jié)以及Web框架的安全交互方面。
●第1章 原型設計和環(huán)境1
1.1 Python中的原型設計1
1.1.1 使用REPL設計原型2
1.1.2 使用Python腳本設計原型5
1.1.3 使用腳本和pdb設計原型6
1.1.4 使用Jupyter設計原型9
1.1.5 本章的原型設計11
1.2 環(huán)境設置13
1.3 創(chuàng)建新項目14
1.3.1 設計腳本原型15
1.3.2 安裝依賴項18
1.4 導出到.py文件20
1.5 構建命令行接口22
1.5.1 sys模塊和argv23
1.5.2 argparse24
1.5.3 click26
1.6 打破界限28
1.6.1 遠程內核28
1.6.2 開發(fā)不能在本地運行的代碼32
1.7 完成后的腳本34
1.8 小結36
更多資源36
●第2章 測試、檢查和linting37
2.1 測試40
2.1.1 何時編寫測試42
2.1.2 創(chuàng)建格式化函數(shù)來提高可測試性43
2.1.3 pytest46
2.2 類型檢查56
2.2.1 安裝mypy57
2.2.2 添加類型提示58
2.2.3 子類和繼承60
2.2.4 泛型類型62
2.2.5 調試以及過度使用類型64
2.2.6 何時使用類型,何時避免使用類型66
2.2.7 將類型提示與代碼分離67
2.3 linting68
2.3.1 安裝flake8和black69
2.3.2 修復現(xiàn)有代碼70
2.3.3 自動運行71
2.3.4 拉取時運行73
2.4 小結74
更多資源75
●第3章 打包腳本76
3.1 術語77
3.2 目錄結構77
3.3 安裝腳本和元數(shù)據80
3.4 依賴項80
3.5 聲明式配置82
3.5.1 在setup.py中需要避免的事項82
3.5.2 使用setup.cfg86
3.6 自定義索引服務器88
3.6.1 創(chuàng)建pypiserver90
3.6.2 持久性91
3.6.3 保密性92
3.6.4 完整性92
3.6.5 wheel格式和在安裝時執(zhí)行代碼93
3.7 使用入口點安裝控制臺腳本95
3.8 README、DEVELOP和CHANGES97
3.8.1 Markdown格式97
3.8.2 reStructuredText格式99
3.8.3 README101
3.8.4 CHANGES.md和版本化101
3.9 上游依賴項版本鎖定103
3.9.1 寬松鎖定103
3.9.2 嚴格鎖定104
3.9.3 應該使用哪種鎖定方案105
3.10 上傳版本105
3.11 小結107
更多資源107
●第4章 從腳本到框架109
4.1 編寫傳感器插件110
4.2 添加新的命令行選項113
4.2.1 子命令113
4.2.2 命令選項116
4.2.3 錯誤處理117
4.2.4 通過實參類型將解析工作
交給click120
4.2.5 自定義click實參類型121
4.2.6 常用選項123
4.3 允許使用第三方傳感器插件124
4.3.1 使用固定名稱檢測插件126
4.3.2 使用入口點檢測插件127
4.3.3 配置文件129
4.3.4 環(huán)境變量132
4.3.5 apd.sensors與類似程序的方法對比133
4.4 小結133
更多資源134
●第5章 其他接口136
5.1 Web微服務136
5.1.1 WSGI137
5.1.2 API設計142
5.1.3 Flask144
5.1.4 Python裝飾器146
5.1.5 測試視圖函數(shù)157
5.1.6 部署159
5.2 將軟件作為第三方軟件擴展160
5.2.1 與其他開發(fā)人員就簽名達成一致165
5.2.2 抽象基類167
5.2.3 后備策略170
5.2.4 綜合運用174
5.3 修復代碼中的序列化問題176
5.4 版本化API180
5.5 小結183
更多資源183
●第6章 聚合過程185
6.1 cookiecutter185
6.2 創(chuàng)建聚合包189
6.2.1 數(shù)據庫類型190
6.2.2 示例192
6.2.3 對象關系映射器193
6.2.4 版本化數(shù)據庫197
6.2.5 加載數(shù)據202
6.3 新技術209
6.3.1 數(shù)據庫210
6.3.2 自定義特性行為210
6.3.3 生成器210
6.4 小結210
更多資源211
●第7章 并行和異步212
7.1 非阻塞IO213
7.2 多線程與多進程218
7.2.1 低級線程219
7.2.2 字節(jié)碼222
7.2.3 鎖與死鎖225
7.2.4 避免全局狀態(tài)229
7.2.5 其他同步原語234
7.2.6 ProcessPoolExecutor241
7.2.7 使代碼使用多線程241
7.3 asyncio242
7.3.1 async def242
7.3.2 await243
7.3.3 async for245
7.3.4 async with249
7.3.5 異步鎖定原語249
7.3.6 使用同步庫251
7.3.7 使代碼異步化252
7.4 比較255
7.5 做出選擇255
7.6 小結257
更多資源258
●第8章 高級asyncio259
8.1 測試異步代碼259
8.1.1 測試代碼260
8.1.2 模擬對象以方便進行單元測試267
8.2 異步數(shù)據庫276
8.2.1 經典SQLAlchemy風格277
8.2.2 使用run_in_executor280
8.2.3 查詢數(shù)據282
8.2.4 避免復雜查詢284
8.2.5 其他方案293
8.3 異步代碼中的全局變量294
8.4 小結296
更多資源297
●第9章 查看數(shù)據298
9.1 查詢函數(shù)298
9.1.1 過濾數(shù)據303
9.1.2 多層迭代器306
9.1.3 其他過濾器312
9.1.4 測試查詢函數(shù)313
9.2 顯示多個傳感器316
9.3 處理數(shù)據319
9.4 與Jupyter小部件進行交互323
9.4.1 增加嵌套的同步和異步代碼324
9.4.2 進行整理329
9.5 持久端點330
9.6 繪制地圖和地理數(shù)據330
9.6.1 新的圖類型333
9.6.2 在apd.aggregation中支持地圖類型的圖335
9.6.3 使用新配置繪制自定義地圖337
9.7 小結339
更多資源340
●第10章 加快速度341
10.1 優(yōu)化函數(shù)341
10.1.1 性能分析和線程343
10.1.2 解讀profile報表345
10.1.3 其他性能分析器348
10.2 優(yōu)化控制流352
10.2.1 可視化性能分析數(shù)據356
10.2.2 緩存360
10.3 小結369
更多資源369
●第11章 容錯371
11.1 錯誤處理371
11.1.1 從容器獲取項372
11.1.2 自定義異常377
11.1.3 涉及多個異常的堆棧跟蹤380
11.1.4 測試異常處理383
11.2 警告388
11.3 日志393
11.3.1 嵌套記錄器394
11.3.2 自定義動作396
11.3.3 記錄配置400
11.3.4 其他處理程序402
11.4 設計時規(guī)避問題402
11.5 小結407
更多資源408
●第12章 回調與數(shù)據分析409
12.1 生成器的數(shù)據流409
12.1.1 使用自己的輸出的生成器411
12.1.2 增強的生成器414
12.1.3 隊列420
12.1.4 選擇控制流422
12.2 動作的結構423
12.2.1 分析協(xié)程424
12.2.2 攝入數(shù)據429
12.2.3 運行分析進程432
12.3 進程狀態(tài)434
12.4 擴展可用的動作439
12.5 小結441
更多資源442
后記443