現代軟體開發越來越複雜,如果還單純的認為學習軟體開發就是學習某某程式語言那估計最多只能寫寫「Hello World」之類的程序了。我不覺得這種「複雜」是一種無病呻吟的病態,相反我認為這是軟體開發技術的進步。系統越來越複雜,團隊協作也越來越突出,這就決定了我們的工具也越來越複雜。工程化可以幫助我們的項目更加規範,讓新成員更加容易理解項目。這篇文章裡我會結合國情來介紹一些Python工程化心得。
python-skeleton
├── README.md #
├── docs #文檔
├── etc #示例配置文件
├── python_skeleton #項目所有代碼
└── tests #測試代碼
上面是我的工程結構,下面我們就要針對這個工程來實現工程化
這樣的代碼結構就是import的災難,除了使用相對引用之外沒有別的辦法,所以這不是一種好的實踐。第一步我們先給工程增加一個setup.py
這麼多配置項沒人能記得住,所以一般情況下我們可以從別的工程中複製setup.py。long_description是一段很長的描述,所以我直接從README.md中讀取整個項目的描述packages描述了哪些Python的包被打包,find_packages會查找當前工程下所有的Python包,通過exclude剔除了不參與打包的。例子中就是單元測試、文檔和示例配置有了setup.py之後我們執行python setup.py develop,這條命令會在site-package中建立一個link,指向我們當前的工程,所以我們的代碼就可以使用絕對引用了。
python_skeleton是我項目所有原始碼所在的包
單元測試被所有軟體工程強調,所以作為工程化的一部分我們必須要給出單元測試的最佳實踐。我的單元測試代碼都在tests包,解決了import的問題後它是可以直接在IDE中執行了。但是一個一個的執行測試用例是非常麻煩的,所以我們希望通過python setup.py test來一次執行所有的單元測試這樣。
修改setup.py,添加一句。我比較懶,所以直接用python unittest 作為單元測試工具,如果你用nose作為單元測試工具需要寫兩句
test_require指定了測試的依賴,在執行python setup.py test的時候會首先下載依賴然後再執行測試。
python最大的特點就是提供了非常非常豐富的第三方包,例如:我的代碼中使用python-click。隨著項目的開發勢必還會增加更多第三方包,如果一個一個的安裝那就太原始了。所以通過工程化我希望可以讓新加入的小夥伴執行一句pip install -r requirements.txt就可以自動安裝所有依賴。
我們新建一個requirements.txt,裡面寫上我們需要的依賴,執行pip的時候直接通過文件安裝依賴。setup.py中也會有依賴,當我們執行python setup.py install的時候這些依賴會被安裝到當前系統中。所以我們希望setup.py中的依賴和requirements.txt的依賴保持一致。
這個功能非常酷,我希望給我的程序增加一個命令行。用戶輸入:python-skeleton就可以執行我的程序了。
setup.py新增加一條,python-skeleton是命令名稱,python_skelecton.cli是類,main是要執行的方法。
我使用python-click為項目增加了兩個參數分別指定配置文件和日誌配置文件。默認是使用/etc下面的
命令行工具自動生成了,我希望還可以把代碼中的兩個配置實例
複製到系統的/etc/python-skeleton中。這樣安裝的時候我們只需要執行python setup.py install就可以成功安裝命令行腳本、自動複製配置文件了,簡直是妙不可言。
總結一下,到目前為止我們有setup.py、requirements.txt兩個文件。通過這兩個配置我們可以
python setup.py develop來安裝開發環境,這樣代碼裡面就可以使用絕對應用
通過pip install -r requirements.txt來安裝依賴
發布的時候通過python setup.py install在目標系統上自動生成命令行腳本,複製配置文件,自動安裝依賴
到目前為止我們可以通過python setup.py sdist來生成壓縮文件
安裝的時候只需要解壓這個文件,然後執行python setup.py install
DUANG,我們收到一個錯誤。提示我們README.md文件找不到,如果我們查看發現壓縮文件裡面沒有README.md和requirements.txt文件。我們的setup.py腳本是通過讀取這兩個文本文件生成配置的,所以在打包的時候需要把這兩個文件也給打包進去。通過新增MANIFEST.in我們實現這個
再執行打包,我們的壓縮裡面就會有這兩個文件
通過上面的步驟我們生成的壓縮包只有我們的代碼,如果發布到生成環境時python setup.py install會幫我們自動下載依賴。遺憾的是——在我朝,通常生產伺服器都是沒有網絡的。所以我們希望可以通過離線的方式把第三方pip下載下來。通過執行pip download -r requirements.txt -d ./pipcache我們可以把依賴下載到pipcache文件夾中(請確保pipcache文件夾存在)在生產環境我們使用pip install --no-index --find-links=pipcache -r requirements.txt通過本地文件夾安裝依賴
好了,到這裡我們的自動化已經完成了。
1. python setup.py develop連結文件,解決import的問題
2. pip install -r requirements.txt 安裝依賴
3. pip download -r requirements.txt -d ./pipcache 下載離線依賴(可選)
1. pip install --no-index --find-links=pipcache -r requirements.txt離線安裝依賴(可選)
2. python setup.py install安裝系統,該命令會生成命令行腳本,複製配置文件
這些命令都太長了,我希望通過一個腳本自動化打包,清除臨時文件(刪除pyc,egg等臨時文件),同時為部署的時候生成一個腳本(畢竟那條離線安裝的命令太長了。。。。)所以我寫了一個Makefile
通過為腳本增加-i http://pypi.douban.com/simple --trusted-host pypi.douban.com選項可以加速PIP的下載。具體參考我的github。
最後貢獻出所有的代碼,我的github上