為什么需要弄腳手架?
平時,主要是開發(fā)一些工具給自己或部門使用,因此對代碼管理比較隨意,也不需要其他人查看或修改代碼。近期,有個工具要推廣給其他人使用,為了方便他們修改代碼,要增加注釋之類的工作。在這個過程中,發(fā)現(xiàn)了一大段問題,比如地址的引用,存在較多相對地址,容易發(fā)生錯誤,代碼命名不規(guī)范等一大堆規(guī)范性問題。
為了改善自己的編碼習(xí)慣、減少規(guī)范性問題,花了一些時間查找、研究Python項目管理的方式,經(jīng)過幾次折騰后,總算確定了自己的項目管理方式(短期內(nèi)應(yīng)該不會再調(diào)整了)。
環(huán)境管理
我原先使用的是Anaconda,但是后面覺得有點臃腫,適合做數(shù)據(jù)分析或機(jī)器學(xué)習(xí),但不太適合做開發(fā),因此改用 pipenv 進(jìn)行環(huán)境管理(機(jī)器學(xué)習(xí)開發(fā)環(huán)境也是用pipenv)。
創(chuàng)建虛擬環(huán)境
pipenv install --python version
上述命令會生成Pipfile和Pipfile.lock,且會使用pipenv創(chuàng)建虛擬環(huán)境,自動生成一個隨機(jī)的虛擬環(huán)境目錄名。般虛擬環(huán)境目錄名的前綴是你創(chuàng)建環(huán)境時所在的項目目錄名,如在myblog目錄下執(zhí)行命令,虛擬環(huán)境的目錄名稱就是myblog-Gtn4e1q9,后半部分為隨機(jī)字符串。
在windows系統(tǒng)下執(zhí)行命令,虛擬環(huán)境的文件 C:\Users\用戶名.virtualenvs 文件夾下。若要修改存儲地址,則要在系統(tǒng)新建【W(wǎng)ORKON_HOME】的環(huán)境變量。
pipenv --venv # 獲取當(dāng)前虛擬環(huán)境的位置
pipenv --where # 尋找當(dāng)前項目的根目錄
激活虛擬環(huán)境
創(chuàng)建環(huán)境后會自動進(jìn)入到虛擬環(huán)境中,當(dāng)退出虛擬環(huán)境重新進(jìn)入到虛擬環(huán)境則需要激活虛擬環(huán)境。
在項目目錄下,執(zhí)行如下命令,即可激活虛擬環(huán)境.
pipenv shell
激活虛擬環(huán)境后,所有的操作僅影響當(dāng)前的虛擬環(huán)境。
包管理
安裝依賴包到虛擬環(huán)境
建議使用pipenv來安裝/卸載相關(guān)包,便于開發(fā)依賴包的管理。安裝與卸載同理,不額外說明。
pipenv install module_name # 安裝生產(chǎn)環(huán)境的依賴包
pipenv install module_name --dev # 安裝開發(fā)環(huán)境的依賴包
不管是否激活虛擬環(huán)境,都可以執(zhí)行pipenv install module_name來安裝。
若要使用pip進(jìn)行安裝,則按如下命令執(zhí)行:
pipenv run pip install module_name
使用pipenv安裝時,可能會出現(xiàn)lock fail。這個讓我苦惱了很久,解決方案如下:
- 跳過lock環(huán)節(jié),先把包安裝上。
pipenv install requests --skip-lock
- 查看安裝包的版本號,并添加到pipfile中。
pipenv graph
3.更新pipfile.lock,重新安裝虛擬環(huán)節(jié)時,依賴這個文件,不能漏了。
pipenv lock --dev
導(dǎo)出/安裝包文件
導(dǎo)出依賴包
pipenv lock -r > requirements_dev.txt # 不包含開發(fā)環(huán)境的依賴包
pipenv lock -r --dev > requirements_dev.txt # 包含開發(fā)環(huán)境的依賴包
也可以使用pip進(jìn)行導(dǎo)出,不過無法區(qū)分開發(fā)環(huán)境的依賴包。
pipenv run pip freeze > requirements.txt
根據(jù)pipfile安裝依賴包
pipenv install # 不包含開發(fā)環(huán)境的依賴包
pipenv install --dev # 包含開發(fā)環(huán)境的依賴包
根據(jù)requirements安裝。
pipenv install -r > requirements.txt
開發(fā)環(huán)境配置
開發(fā)環(huán)境配置,主要關(guān)注幾點:代碼風(fēng)格統(tǒng)一、靜態(tài)類型檢查、單元測試。
使用black進(jìn)行格式化我們的代碼。--dev用來區(qū)分開發(fā)環(huán)境,不要忘了。
pipenv install black --dev # 安裝
pipenv run black file_name/dir_name # 運(yùn)行
使用isort對import進(jìn)行管理。
pipenv install isort --dev # 安裝
pipenv run isort file_name/dir_name # 運(yùn)行
使用 flake8 保證代碼風(fēng)格,可以參考谷歌Python風(fēng)格指南。
pipenv install flake8 --dev # 安裝
pipenv run flake8 file_name/dir_name # 運(yùn)行
使用 mypy 進(jìn)行靜態(tài)類型檢查。不過,Python的類型注釋還是不好用。
pipenv install mypy --dev # 安裝
pipenv run mypy file_name/dir_name # 運(yùn)行
用 pytest 進(jìn)行測試,我用的比較少,實在是懶得寫測試代碼。
pipenv install pytest --dev # 安裝
pipenv run pytest # 運(yùn)行
以上就是主要的開發(fā)環(huán)境內(nèi)容,但是每次手動執(zhí)行還是比較麻煩的。因此,需要用到 Git 的 pre-commit,在提交代碼前自動執(zhí)行相關(guān)命令。這里需要用到 pre-commit 庫。
pipenv install pre-commit --dev
然后新建.pre-commit-config.yaml,并添加下述配置。
repos:
- repo: local
hooks:
- id: isort
name: isort
stages: [commit]
language: system
entry: pipenv run isort {{cookiecutter.project_slug}}
types: [python]
- id: black
name: black
stages: [commit]
language: system
entry: pipenv run black {{cookiecutter.project_slug}}
types: [python]
- id: flake8
name: flake8
stages: [commit]
language: system
entry: pipenv run flake8 {{cookiecutter.project_slug}}
types: [python]
exclude: setup.py
- id: mypy
name: mypy
stages: [commit]
language: system
entry: pipenv run mypy
types: [python]
pass_filenames: false
- id: pytest
name: pytest
stages: [commit]
language: system
entry: pipenv run pytest
types: [python]
最后,執(zhí)行下述命令生成git hooks。
pipenv run pre-commit install
快速創(chuàng)建項目
開發(fā)環(huán)境的配置還是有較多內(nèi)容,為了減少重復(fù)工作,需要用到 cookiecutter 進(jìn)行項目創(chuàng)建。我已經(jīng)將上述內(nèi)容整合到項目模板中,執(zhí)行如下命令可直接創(chuàng)建項目。
pip install cookiecutter # 不用安裝到虛擬環(huán)境。
cookiecutter https://e.coding.net/jinuobushibili/zzz_tools/ProjectTemplate.git
除上述內(nèi)容外,項目模板中還包含項目目錄、項目配置等多項內(nèi)容。
項目代碼結(jié)構(gòu)
- docs(dir):項目文檔庫
- template(dir):模板文件庫
- bin(dir):入口文件,可無
- db(dir):數(shù)據(jù)文件地址
- log(dir):項目日志文件
- conf(dir):項目配置文件
- tests(dir):測試代碼
- lib(dir):自定義的模塊或包
- sample(dir):關(guān)鍵代碼文件,每個包單獨(dú)目錄
- _ init _.py
- main.py
- setting.py:添加了部分目錄的路徑變量,如db。
- README.md:項目說明文檔
- requirements.txt:項目依賴的三方庫
- setup.py:安裝、部署、打包代碼
修改項目模板
若要基于自己的需求,對項目模板進(jìn)行修改的話,也是比較簡單的。
變量修改
cookiecutter變量,通過 cookiecutter.json 進(jìn)行修改。其中的值為默認(rèn)值,在創(chuàng)建項目時,會要求再次確認(rèn)。而變量的使用,只需在對應(yīng)的文件中,使用 {{ 變量名 }}即可。但需保證文件的編碼為utf-8。
目錄/文件調(diào)整
cookiecutter生成的文件目錄是{{cookiecutter.project_slug}},需要項目自動生成的文件要放到這個目錄下。
在{{cookiecutter.project_slug}}目錄下操作即可,對根目錄下其他目錄的修改是不會影響創(chuàng)建項目的。
開發(fā)環(huán)境調(diào)整
調(diào)整完以后,記得更新requirem或pipfile即可。相關(guān)操作,請查看上方對應(yīng)內(nèi)容。
Hooks
cookiecutter的hooks全部在hooks目錄下。
- pre_gen_project.py:項目創(chuàng)建前
- post_gen_project.py:項目創(chuàng)建后
結(jié)合cookiecutter變量與hooks,可以進(jìn)行許多復(fù)雜的操作。我還沒怎么用。