告別 Anaconda:在 macOS 上使用 pyenv 建立 Python 開發環境
文章目錄
by Koma Zhang
2024/04/25
:新增「更新 Python 版本」。
「人生苦短,我用 Python」闡述了 Python 的易用與簡潔,但如果深入到 Python 的套件管理與版本隔離,則是一件十分複雜的事,有興趣的人可以參考下列內容:
- 撥開 Python, pip, site-packages 的藍色蜘蛛網 💢
- 《捕蛇者說》Ep 15. 和 PyPA 的成員聊聊 Python 開發工作流(推薦!)
- 建立一個方便開發的 Python 環境 (零)- 使用 Pyenv 管理 Python 版本
- pip, pipenv 和 poetry 的選擇
本文重點
這次並沒有要細論上述內容,只是想把 Anaconda 移除掉——我現在的 Python 虛擬環境(virtualenv)都是用 Anaconda 附帶的 conda 建立與管理居多。
而最常見的替代方案,就是 pyenv + virtualenv。
本篇僅記錄一下設定上的重點,詳細用法請參考 pyenv 官方 GitHub。
為何要從 conda 轉向 pyenv?
主要是為了「簡潔」。另外,使用 pyenv 可以更方便地管理不同版本的 Python,切換上的靈活性不是 conda 所能比的。
所有用 conda 建立的虛擬環境都同時可以用 pip 或 conda 來安裝第三方套件,這樣容許混雜的模式讓我略感煩躁。
其次是 conda 預設的 base env 真的很肥大,畢竟幫你灌好了一堆資料科學套件。雖然方便,但也往往一併安裝了許多你根本用不上的東西,可謂雙面刃。
不同層級的虛擬環境管理:Python vs 專案
值得一提的是,「不同 Python 版本間的虛擬環境管理」和「不同專案間的虛擬環境管理」基本上是兩件事,只不過 Anaconda 透過 conda 同時都能做到而已。conda 在建立虛擬環境的同時會要求你選擇 Python 版本,所以不同 conda env 間的 Python 版本可以不同。
而 pyenv 則是比較偏向 Python 版本管理,雖然你要直接當套件管理的虛擬環境來用也未嘗不可,但還是推薦使用 virtualenv 較為合理。
Python 層級的虛擬環境管理方案
不在本機的全域直接安裝 Python,而是透過不同的隔離手段,安裝並管理複數版本的 Python,方便不同專案與需求使用。
- conda:即將捨棄。
- pyenv:本文重點。
- Docker:以容器建立開發環境也是一個趨勢,比如 VS Code 的 DevContainer,這部分在此先不討論。
jetbrains.com/lp/python-developers-survey-2020
單一專案虛擬環境管理方案
一般定義上的 Python 虛擬環境,著重於專案所安裝的套件與套件版本。
- Python 內建的 venv:通常直接放在特定專案的根目錄底下,因為沒有更高層的封裝讓你可以輕鬆跨專案打開,路徑要自己找,較適合單一專案使用。
- virtaulenv:最常見的虛擬環境管理方案。
- pyenv-virtualenv:pyenv 的 virtualenv 高階封裝版本。
- Pipenv、Poetry 等套件管理工具:前者小荒廢,後者還很新,主要的亮點都是在處理套件之間的版本依賴問題,現階段暫時不考慮。
以上都只是套件管理,如果要連同 Python 的版本一起管理(這顯然是個硬需求),還是需要 pyenv。
安裝、設定 pyenv
1 | brew update |
裝完之後要設定.bashrc
或.zshrc
,還有.bash_profile
或.zprofile
,端視你的 shell 是哪個。目前新版本的 macOS 預設 shell 為 zsh。
2023/04/07
重要更新:pyenv 2.3.0 以後,已經大幅簡化了設定操作,本段內容在新版仍可適用,但建議直接升級最新版 pyenv 並直接改用以下設定:
1 | export PYENV_ROOT="$HOME/.pyenv" |
官方的 shell 指令版本(for zsh):
1 | echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc |
這三行設定,無論 bash 或 zsh 皆同;.profile
或 .zprofile
如果需要,增加的內容也完全一樣!真的簡化了很多,不用再去判斷是哪種 shell 了。
zsh 使用者
設定的內容主要是提供正確的 Python PATH,這部分很關鍵。具體要新增什麼內容,各教學或官方的版本沒有完全一致,不過大同小異,在此提供我實際新增的部分,注意以下皆是以 Homebrew 安裝的 pyenv 為例:
.zprofile
新增
你可能跟我一樣一開始也沒有這個檔,直接用官方給的指令新增就好:
1 | echo 'eval "$(pyenv init --path)"' >> ~/.zprofile |
.zshrc
新增
1 | if command -v pyenv 1>/dev/null 2>&1; then |
特別說明,官方教學只說需要新增中間的eval "$(pyenv init -)"
,但我光這樣設定,會無法切換全域 Python 版本,看了這篇之後改成上述的版本。
設定好後記得要分別 source 一下。
bash 使用者
如果是 bash 用戶,建議設定上一律直接使用官方提供的這兩段 script 就好了,最簡單無腦且不會出錯,記得兩個部分都要執行喔!
第一部分
1 | echo -e 'if shopt -q login_shell; then' \ |
不過要稍為注意一下.profile
名稱,在 macOS 上通常為.bash_profile
:
1 | echo -e 'if [ -z "$BASH_VERSION" ]; then'\ |
第二部分
1 | echo 'if command -v pyenv >/dev/null; then eval "$(pyenv init -)"; fi' >> ~/.bashrc |
上述設定完後記得要source
或重啟 shell。
安裝 pyenv-virtualenv
請直接參考另一篇文章的內容。
簡單使用案例
以我的例子:
- 建立一個全域的 Python 3.7.11 環境。
- 非必要:將當前 shell 的 Python 版本切換到 3.8.10
- 建立一個使用 Python 3.7.11 的虛擬環境。
1 | #1 |
如果已經在 pyenv 的 3.7.11 環境下,則上述 #2 的3.7.11
可以省略,只要pyenv virtualenv my_venv
即可建立虛擬環境。
啟用與停止虛擬環境
1 | pyenv activate my_venv |
移除虛擬環境
1 | pyenv uninstall my_venv |
查看目前所有虛擬環境
1 | pyenv virtualenvs |
你會看到每一個虛擬環境都有兩個項目,這是正常的:
There are two entries for each virtualenv, and the shorter one is just a symlink.
像下面這樣:
1 | 3.7.11/envs/my_venv (created from /Users/kyo/.pyenv/versions/3.7.11) |
更新 Python 版本
使用指令查看當前所有可安裝的 Python 版本:
1 | pyenv install --list |
安裝 pyenv 後,用了一段時間,可用的 Python 版本一定會有更新,但 pyenv 並不會自動更新這些 Python 版本。
可以使用以下指令更新 pyenv(使用 homebrew 安裝):
1 | brew upgrade pyenv |
或參考其它更新方式
1 | pyenv update |
或
1 | cd $(pyenv root) |
結論
使用 pyenv 建立不同 Python 版本並管理相對應的虛擬環境實在非常方便!
附帶一提,雖然不一定要安裝 pyenv-virtualenv 而可以直接pip virtualenv
即可,但後者的使用方式類似內建的 venv,比較沒有那麼彈性。
此外,pyenv-virtualenv 在 3.3 版本以上的 Python,實際上就是調用內建的 venv 來建立虛擬環境,否則就是調用 virtualenv,總之就是多一層封裝讓使用變得更方便而已。
參考
相關文章