pipenv
用來管理 python 的 app 是不錯(注意不是模組,模組還是該用 distutils
),不過基於 python 社群的一貫風格還是要搞點問題出來才行。先前碰到 issue 2364,搞了好久才全部弄清楚。背景知識要先知道 pyvenv
, pyenv
, virtualenv
, pip
, pipenv
這一堆東西是幹嘛的(stackoverflow 上的說明),然後要知道 virtualenv
會綁初始 pip
, setuptools
, wheel
的版本,就比較容易弄清楚了。
狀況是:在 Ubuntu 19.04 上面用 pipenv
設定開發的專案,Python 版本綁在系統預設的 3.6. 後來移到 20.04,由於系統版本升到 3.8,所以先裝 pyenv
然後再 pipenv sync
,理論上這樣 pipenv
會先用 pyenv
裝好 3.6、產生執行 3.6 版的 virtualenv
、然後裝好所有需要的模組。但最後在安裝模組階段噴錯。研究後發現裡面用到的模組需要較新的 setuptools
版本才能正確安裝,而版本是由 virtualenv
產生環境時決定的,但 pipenv
的開發者認為 virtualenv
屬於使用者環境的一部分,他們不應該去修改,使用者一番爭論後答應看一看,就又沒下文了。
當安裝 pipenv
時 (python3 -m pip install pipenv
),由於 virtualenv
是一個 dependency,所以會先檢查有沒有符合的版本,沒有的話會自動帶入。這就是在 20.04 那邊出錯的原因,因為 19.04 的系統沒裝 python3-virtualenv
但 20.04 的系統有,所以最早在 19.04 那台安裝 pipenv
時帶入了新版的 virtualenv
,比 20.04 系統裡面預設安裝的新,所以一直沒問題。移到 20.04 時,pip
檢查到 virtualenv
已經存在,就用現有的,所以產生的環境裡面 setuptools
比較舊,安裝模組時就失敗了。
這邊要注意的是: pyenv
在這邊的作用,並不及於 pipenv
以及 virtualenv
. 也就是說,在預設為 3.8 的系統上跑 pipenv install
時,是用 3.8 搭配的 pipenv
,自然也執行到了 3.8 搭配的 virtualenv
. 直到以 pipenv shell
或者 pipenv run
的時候,被執行的程式才會真正用到虛擬環境裡的 python 版本,也就是 3.6.
知道以上資訊後,解法也很簡單。不管系統裡面有沒有 virtualenv
,反正都用 python3 -m pip install --user virtualenv
在 home 底下裝一份新的就好。這也表示在重建 build 環境時,除了 Pipfile 裡面已經綁死的東西,也要注意用到的 virtualenv
版本是否相容。