2018-02-10 | 1 Comment 前面的這一篇、這一篇、和這一篇介紹了介紹了 Python 套件的安裝基本概念,與 pip 和 venv 的使用時機。但就像前面已經提到的,pip 在後續的套件更新與維護相依性的一些細節會有瑣碎的事情要處理,而且每次開一個專案就要手動建立一個虛擬環境,還是有點麻煩。有沒有更懶惰的作法阿… 懶惰是工程師美德,是的,所以 pipenv 就誕生了。這個工具主要解決了以下痛點: 以前都要手動建立虛擬環境,以後不用了,由 pipenv 自動幫你處理 致敬 PHP 的 Composer(好啦可能不是致敬,但我真的覺得很像),提供了 Pipfile 和 Pipfile.lock 機制來讓我們更好管理套件相依,後面會有範例。 Talk is cheap. Show me the code. 廢話不多說,直接上範例說明吧。 安裝 pipenv 因為 pipenv 還是個活躍開發的新專案,所以目前大部分的 distro 都不會包這個套件,即便有包,版本也是舊的。 我個人習慣是,這類常用且我想追新版本的工具(ansible, cookiecutter, mercurial, etc.),我會建立一個 ~/venv/tools 的虛擬環境,然後把這些套件都裝在這裡面使用。所以來把 pipenv 也裝在這裡吧: $ mkdir ~/venv/ $ python3 -m venv ~/venv/tools # 記得要裝 python3-venv 才有 venv module 可以用 $ ~/venv/tools/bin/pip install pipenv # 使用虛擬環境裡的 pip 安裝 pipenv 然後設定你的 shell PATH 將 ~/venv/tools/bin 也加到搜尋路徑,之後就可以用囉。從此刻開始,不要再操作 pip 安裝移除套件了,請改用 pipenv 工具。 在專案中初始化 pipenv 在專案中要使用 pipenv 很簡單,下個指令就好: $ cd /your/project/path $ pipenv install pipenv 會自動的建立一個虛擬環境,且在你的當前目錄下建立 Pipfile 與 Pipfile.lock。這兩個檔案的差別在,Pipfile 是紀錄你的專案直接相依的套件列表,而 Pipfile.lock 則是用 JSON 格式紀錄整個套件相依的完整列表,就像是 pip freeze 指令所產生的列表一樣,只是是用 JSON 的格式存放紀錄。 至於 pipenv 建立的虛擬環境在哪?你可以執行以下的指令得知完整路徑: $ pipenv --venv 或是之後你不需要這個虛擬環境了,想刪掉也可以: $ pipenv --rm 使用 pipenv 於專案中安裝套件 跟 pip 用法很像,比方我們要用 pipenv 裝 requests 套件: $ pipenv install requests 安裝完後,Pipfile 會長的像這樣: [[source]] url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" [dev-packages] [packages] requests = "*" 可以看到 requests 的確被紀錄進去了,後面的 * 代表安裝的是最新版。至於我們到底是裝了哪個版本,以及額外裝了哪些相依套件,要去看 Pipfile.lock: { "_meta": { "hash": { "sha256": "a0e63f8a0d1e3df046dc19b3ffbaaedfa151afc12af5a5b960ae7393952f8679" }, "host-environment-markers": { "implementation_name": "cpython", "implementation_version": "0", "os_name": "posix", "platform_machine": "x86_64", "platform_python_implementation": "CPython", "platform_release": "4.9.0-5-amd64", "platform_system": "Linux", "platform_version": "#1 SMP Debian 4.9.65-3+deb9u2 (2018-01-04)", "python_full_version": "2.7.13", "python_version": "2.7", "sys_platform": "linux2" }, "pipfile-spec": 6, "requires": {}, "sources": [ { "name": "pypi", "url": "https://pypi.python.org/simple", "verify_ssl": true } ] }, "default": { "certifi": { "hashes": [ "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296", "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d" ], "version": "==2018.1.18" }, "chardet": { "hashes": [ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" ], "version": "==3.0.4" }, "idna": { "hashes": [ "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" ], "version": "==2.6" }, "requests": { "hashes": [ "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" ], "version": "==2.18.4" }, "urllib3": { "hashes": [ "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" ], "version": "==1.22" } }, "develop": {} } 這邊可以看到其實總共裝了 certifi、chardet、idna、requests、urllib3 共 5 個套件,其中也包含了版本資訊。 藉由 Pipfile 和 Pipfile.lock 把直接相依與間接相依的列表分開的設計,我們可以更容易的去了解這個專案的相依套件狀況。 使用 pipenv 於專案中移除套件 移除也很直覺,下個 uninstall 就移除了: $ pipenv uninstall requests 檢查一下 Pipfile 和 Pipfile.lock… 哇,讚喔,移掉 requests 後,pipenv 連帶分析了其他 4 個套件也不再需要,所以一起於 Pipfile.lock 移除了。 使用 pipenv 於專案中更新套件 這也很簡單,一行指令解決: $ pipenv update 它的行為是,會先將所有安裝的套件移除,然後重新安裝在 Pipfile 中 [packages] 區段所列的套件至最新版,這樣也可以確保整個相依的關係是最乾淨的。 使用 pipenv 於專案中安裝開發用套件 這功能很實用阿… 有時候我們開發環境會需要一些特別的套件,比方 pytest。但實際在佈署到線上環境時,這類開發套件是不需要一起裝上去的。這時你可以在安裝這類的套件時,加個 –dev 參數: $ pipenv install pytest --dev 這樣,pipenv 就會把 pytest 紀錄為開發用的套件,在 Pipfile 中會歸類在 [dev-packages] 區段中。這樣實際上在佈署時,只要執行 pipenv install 時不加上 –dev 參數,這些開發用套件就不會被安裝囉。 常用的幾個功能大概就是這些,剩下的遺珠,請自行參閱官方文件:https://docs.pipenv.org/