教你如何閱讀 Python 開源項目代碼
- 2020 年 2 月 12 日
- 筆記
來源:https://learnku.com/articles/23010/teach-you-to-read-the-python-open-source-project-code
為什麼要閱讀開源代碼
閱讀 Python 開源項目代碼主要有如下三個原因:
- 在工作過程中遇到一些問題 Google 和 StackOverFlow 等網站找不到解決辦法,只能去翻源碼。
- 對某些項目或者方向非常感興趣,希望深入。
- 學習遇到瓶頸需要汲取開源項目的經驗和用法來做提高。
要有目的的閱讀開源項目
沒有目的的閱讀開源項目就是耍流氓,浪費了時間,但是能學到的東西也很少。怎麼樣根據自身情況去閱讀呢?
- 和興趣以及工作契合。舉個例子,工作中沒有機會用到 Celery 又不是想自己造個輪子,讀它的源碼做什麼?所以要從平時能接觸到的那些項目中選取。有時候不去看 Django 的代碼,因為日常工作基本遇不到,遇到了現翻就好了。
- 一個方向只看一兩個典型的就可以了。比如 Web 框架只看過 Bottle 和 Flask 的源碼。
- 清楚自己看代碼的目的。就是你看代碼是想了解人家怎麼設計、調試 BUG、還是只是想學習正確的編程用法呢?其實沒有必要細摳每個代碼細節,有時候當黑盒看,知道輸入輸出就可以了。
優秀的開源作者
和工作中看別人代碼差不多,基本每個人、每個項目、每個團隊都有自己寫代碼的風格,比如變量命名風格、某些語言特性使用方式、代碼規範要求、目錄風格等,其實開源項目的作者也是一樣。看代碼,如看人「團隊」
- kennethreitz Requests 和 Python-guide 作者。他還有一個非常勵志的故事,有興趣的可以看 誰說程序員不是潛力股?
- mitsuhiko flask、Jinja2、werkzeug 和 flask-sqlalchemy 作者。
- sigmavirus24 flake8、pycodestyle「原 pep 8」、requests、urllib3 等項目的主要貢獻者和維護者。
- ask Celery 及相關依賴的作者。
- ajdavis mongo-python-driver「pymongo」、tornado 等項目的主要貢獻者。
- bitprophet fabric、paramiko「Python 的 ssh 庫」作者。
前 2 個是公認的 Python 領域代碼寫的最好的、最有創意的工程師。
初學者推薦閱讀項目
初學者可以先閱讀一些代碼量比較少的,最好是單文件的項目:
- GitHub – kennethreitz/pip-pop: Tools for managing requirements files
(https://github.com/heroku-python/pip-pop)
- GitHub – kennethreitz/envoy: Python Subprocesses for Humans™.
(https://github.com/not-kennethreitz/envoy)
- GitHub – kennethreitz/records: SQL for Humans™
(https://github.com/kennethreitz/records)
- GitHub – mitsuhiko/pluginbase: A simple but flexible plugin system for Python.
(https://github.com/mitsuhiko/pluginbase)
- GitHub – mitsuhiko/pipsi: pip script installer
(https://github.com/mitsuhiko/pipsi/)
- GitHub – mitsuhiko/unp: Unpacks things.
(https://github.com/mitsuhiko/unp)
- GitHub – chrisallenlane/cheat
(https://github.com/chrisallenlane/cheat/)
- GitHub – jek/blinker: A fast Python in-process signal/event dispatching system.
(https://github.com/jek/blinker)
看代碼主要是了解別人寫代碼的方式,語法實踐這些內容。看完之後,你可以針對這些項目能解決的問題自己寫個項目,寫完之後和上述項目去對比一下,看看哪些方面做的不好。
進階閱讀項目
進階的時候就要閱讀一些相對複雜的項目,它們能幫助你提升 Python 編程技巧:
- faif/python-patterns(https://github.com/faif/python-patterns) 使用 Python 實現一些設計模式的例子。
- pallets/werkzeug(https://github.com/pallets/werkzeug) flask 的 WSGI 工具集。其中包含了實現非常好的 LocalProxy、cached_property、import_string、find_modules、TypeConversionDict 等。
- bottlepy/bottle(https://github.com/bottlepy/bottle) 閱讀一個 Web 框架對 Web 開發就會有更深刻的理解,flask 太大,bottle 就 4k 多行,當然如果你有毅力和興趣直接看 flask 是最好了的。
- msiemens/tinydb(https://github.com/msiemens/tinydb) 了解用 Python 實現數據庫。
- coleifer/peewee(https://github.com/coleifer/peewee) 了解 ORM 的實現。
- pallets/click(https://github.com/pallets/click) click 已經內置於在 flask 0.11 里,提供命令行功能,值得閱讀。
- mitsuhiko/flask-sqlalchemy(https://github.com/pallets/flask-sqlalchemy) 了解一個 flask 插件是怎麼實現的。
除此之外 Web 開發者可以閱讀一些相關的項目:
- runscope/httpbin(https://github.com/kennethreitz/httpbin) 使用 flask
- jahaja/psdash(https://github.com/Jahaja/psdash) 使用 flask 和 psutils 的獲取 Linux 系統信息的面板應用。
- pallets/flask-website(https://github.com/pallets/flask-website) flask 官方網站應用。
- pypa/warehouse(https://github.com/pypa/warehouse) 如果你使用 pyramid,這個 新版的 PYPI 網站 可以幫助你理解很多。
500 Lines
推薦一個非常厲害的項目 GitHub – aosabook/500lines(https://github.com/aosabook/500lines): 500 Lines or Less, 它裏面包含了 22 個由該領域的專家完成,用不到 500 行的代碼實現一個特定功能的子項目。連 Guido van Rossum 都親自來寫基於 asyncio 爬蟲了,Nick Coghlan、ajdavis 也出場了。
不要畏懼
大家都經常會感嘆 XXX 強大,YYY 流行,無形中你會把它放在一個不可觸及到的地位,感覺它很難,而令自己不敢去挑戰它。其實是人就會產出 bug,假如你發現它有問題,就應該抓住機會去驗證它。這個過程中,它的神秘感也就消失了,有過這麼幾次經驗你就有信心了。其次是不要怕你提交的 PR 被拒絕。這是非常正常的,我有很多 PR 是被拒絕的,尤其是給標準庫提交的 Patch,絕大多數都被拒絕了。
帶着問題去閱讀代碼
這也是我認為最有效的方式。這會讓你在閱讀時候有個主線,比較有針對性。
斷點調試
在 Python 代碼中使用 pdb 一般不太好使,因為代碼複雜的話,這種斷點需要你使用多個 N 跳到對應的位置,我一般都是先拋出異常,然後使用 pdb 的 up、down、n
等命令調試。當然在目標位置添加一些 print 日誌或注釋部分代碼然後直接使用 exit()
退出也是可以的。
善用文檔
閱讀一個項目一開始會有點無從下手,那麼就先好好這些內容,它們一般都是作者表達這個項目的第一個入口。quickstart、tutorial 等內容中的最小化的例子其實就是最好的閱讀入口,先去看這些引用的模塊和調用的對應方法或者函數的對應實現,從下至上去閱讀。
理解作者的思考方式
不同的項目要有不同的思考方式來閱讀,不要擰着自己的習慣去閱讀,這樣會很累,得嘗試接受別人的觀點,甚至於改變自己。
閱讀項目的早期版本
一些項目隨着時間演進已經非常複雜了,讀起來有難度,那麼你可以回到項目的早期版本上,先去看相對簡單地版本,然後設置幾個時間點或者版本節點,漸進的來閱讀。
記憶並繪製項目架構
項目就是一堆代碼的組合,除了學習編程技巧,還要了解項目的架構決策,這對於未來自己寫大型項目非常用用。這種理解越補充,你會對它就越來越清晰