你是否有過這樣的經歷,收到一件不錯的生日禮物或圣誕禮物,但是打開后卻發現送你的人忘了買電池?Python的“內置電池”哲學讓作為程序員的你不會遇到這類問題,只要安裝了Python,就擁有了完成任何功能所需的一切條件。
然而,Python標準庫的開發者并不能預測你要實現的“任何”功能到底是什么。即使可以,大多數人也不想去處理一個幾個GB的文件下載,即使可能只是需要寫一個重命名文件的腳本。關鍵在于,即使擁有所有的擴展功能,仍然有許多功能是Python標準庫沒有涵蓋的。不過,這并不是說有些事情是根本無法用Python實現的,這只是表明有些事情可能需要使用外部庫。
Python標準庫是安全且范圍明確的:模塊文檔化程度很高,并且有足夠多的人在經常使用它,從而可以保證在你想使用它時肯定不會遇到麻煩。而且,就算萬一出了問題,也能確保在短時間內有人解決。但是,外部庫就像是地圖上標著“熊出沒,請注意”的部分:可能缺少文檔,功能有bug,更新較少或根本不更新。任何正式的項目都可能用到一些只有外部庫提供的功能,但是需要謹記使用這些外部庫可能帶來的風險。
下面是來自一線的案例。OpenStack使用了SQLAlchemy(<http://www.sqlalchemy.org/>)——一個Python數據庫開發工具包。如果了解SQL的話會知道,數據庫的結構是會發生變化的,所以OpenStack還使用了sqlalchemy-migrate(<https://code.google.com/p/sqlalchemy-migrate/>)來處理數據庫模式的升級。一切運行良好,直到有一天它們不行了,開始出現大量bug,并且沒有好轉的跡象。而且,OpenStack在當時是想要支持Python 3的,然而沒有任何跡象表明sqlalchemy-migrate要支持Python 3。因此,顯然sqlalchemy-migrate已經死了,我們需要切換到其他替代方案。截止到作者寫作時,OpenStack正準備升級到Alembic([https://pypi. python.org/pypi/alembic](https://pypi.python.org/pypi/alembic)),雖然也有一些工作要做,但好在不是那么痛苦。
所有這些引出一個重要的問題:“如何保證我不會掉進同樣的陷阱里?”很遺憾,沒辦法保證。程序員也是人,沒什么辦法可以確保目前維護良好的庫在幾個月后仍然維護良好。但是,在OpenStack中我們使用下列檢查表來根據需要給出建議(我建議你也這么做)。
- Python 3兼容。盡管現在你可能并不準備支持Python 3,但很可能早晚會涉及,所以確認選擇的庫是Python 3兼容的并且承諾保持兼容是明智的。
- 開發活躍。GitHub(<http://github.com>)和Ohloh(<http://www.ohloh.net/>)通常提供足夠的信息來判斷一個庫是否有維護者仍然在工作。
- 維護活躍。盡管一個庫可能是“完成”狀態(即功能完備,不會再加入新功能),但應該有維護者仍然在工作,以確保沒有bug。可以通過查看項目的跟蹤系統來看維護者對bug的反應是否迅速。
- 與各個操作系統發行版打包在一起。如果一個庫被打包在主流的Linux發行版內,說明有其他項目依賴它,所以,如果真有什么問題,至少你不是唯一一個抱怨的。如果打算公開發布你的軟件,那么這項檢查也是很有用的。因為如果軟件的依賴已經在終端用戶的機器上安裝了,顯然分發你的軟件會更容易。
- API兼容保證。沒有比你的軟件因為一個它依賴的庫發生了變化而使整個API崩潰更糟的了。你一定很想知道選擇的庫在過去是否發生過類似的事件。
- 許可證。
盡管可能工作量巨大,但這一檢查表對于依賴同樣適用。如果知道應用程序會大量依賴一個特定的庫,那么至少應該對這個庫的每一個依賴使用這個檢查表。
不管最終使用哪個庫,都要像其他工具一樣對待,因為即使是有用的工具也可能會造成嚴重的損害。盡管不常發生,但問問你自己:如果你有一把錘子,你會拿著它滿屋跑因而可能意外地損壞屋子里的東西,還是會把它放在工具架上或者車庫里,遠離那些貴重而易碎的東西,僅在需要的時候才拿出來?
對于外部庫道理是一樣的,不管它們多么有用,都需要注意避免讓這些庫和實際的源代碼耦合過于緊密。否則,如果出了問題,你就需要切換庫,這很可能需要重寫大量的代碼。更好的辦法是寫自己的API,用一個包裝器對外部庫進行封裝,將其與自己的源代碼隔離。自己的程序無需知道用了什么外部庫,只要知道API提供了哪些功能即可。想要換一個不同的庫?只需要修改包裝器就可以了。只要它仍然提供同樣的功能,那么完全不需要修改其余的核心代碼。也許會有例外,但應該不會太多。大部分庫都被設計成只專注解決一定范圍的問題,因此很容易隔離。
5.7.3節將會涉及如何使用入口點構建驅動系統(driver system),這個系統讓你可以將項目的某些部分設計成可以根據需要切換的模塊。
- 內容提要
- 中文版序
- 前言
- 第1章 項目開始
- 1.1 Python版本
- 1.2 項目布局
- 1.3 版本編號
- 1.4 編碼風格與自動檢查
- 1.5 Joshua Harlow訪談
- 第2章 模塊和庫
- 2.1 導入系統
- 2.2 標準庫
- 2.3 外部庫
- 2.4 框架
- 2.5 Doug Hellmann訪談
- 第3章 管理API變化
- Christophe de Vienne訪談
- 第4章 時區陷阱
- 第5章 文檔
- 5.1 Sphinx和reST入門
- 5.2 Sphinx模塊
- 5.3 擴展Sphinx
- 第6章 分發
- 6.1 簡史
- 6.2 使用pbr打包
- 6.3 Wheel格式
- 6.4 包的安裝
- 6.5 和世界分享你的成果
- 6.6 Nick Coghlan訪談
- 6.7 入口點
- 6.7.1 可視化的入口點
- 6.7.2 使用控制臺腳本
- 6.7.3 使用插件和驅動程序
- 第7章 虛擬環境
- 第8章 單元測試
- 8.1 基礎知識
- 8.2 fixture
- 8.3 模擬(mocking)
- 8.4 場景測試
- 8.5 測試序列與并行
- 8.6 測試覆蓋
- 8.7 使用虛擬環境和tox
- 8.8 測試策略
- 8.9 Robert Collins訪談
- 第9章 方法和裝飾器
- 9.1 創建裝飾器
- 9.2 Python中方法的運行機制
- 9.3 靜態方法
- 9.4 類方法
- 9.5 抽象方法
- 9.6 混合使用靜態方法、類方法和抽象方法
- 9.7 關于super的真相
- 第10章 函數式編程
- 10.1 生成器
- 10.2 列表推導
- 10.3 函數式函數的函數化
- 第11章 抽象語法樹
- 11.1 用抽象語法樹檢查來擴展flake8
- 11.2 Hy
- 11.3 Paul Tagliamonte訪談
- 第12章 性能與優化
- 12.1 數據結構
- 12.2 性能分析
- 12.3 有序列表和二分查找
- 12.4 namedtuple和slots
- 12.5 memoization
- 12.6 PyPy
- 12.7 通過緩沖區協議實現零復制
- 12.8 Victor Stinner訪談
- 第13章 擴展與架構
- 13.1 多線程的注意事項
- 13.2 多進程與多線程
- 13.3 異步和事件驅動架構
- 13.4 面向服務架構
- 第14章 RDBMS和ORM
- 14.1 用Flask和PostgreSQL流化數據
- 14.2 Dimitri Fontaine訪談
- 第15章 Python 3支持策略
- 15.1 語言和標準庫
- 15.2 外部庫
- 15.3 使用six
- 第16章 少即是多
- 16.1 單分發器
- 16.2 上下文管理器
- 第17章 延伸閱讀
- 版權信息
- 版權聲明
- 歡迎來到異步社區!
- 異步社區的來歷
- 社區里都有什么?
- 購買圖書
- 下載資源
- 與作譯者互動
- 靈活優惠的購書
- 紙電圖書組合購買
- 社區里還可以做什么?
- 提交勘誤
- 寫作
- 會議活動早知道
- 加入異步