我算 python 新手, 因此這篇筆記只是記錄我的安裝步驟而已.
在閱讀資料的過程中, 第一個想法是工具怎麼這麼多, 真怕把環境搞爛了.
學習目標如下
我要怎麼管理 python 版本?
我不希望套件全部都在 python 版本內, 而是要依據專案需求配置.
套件依賴希望可以類似 package.json 做版控.
Dev Env
簡單介紹我的配置與環境.
MacOS
Homebrew
zsh (with
oh my zsh
framework)VsCode
大概是寫過 NodeJs, 因此有了 nvm 的概念跟踩過一些環境配置的雷. 而 MacOs 本身就自帶 python2, 若執行了 pip 安裝套件依賴, 我可能會搞不清楚這些 dependencies 到底安裝到什麼神秘空間去了. 環境爛了, 可能也影響了 MacOs 的某些需要依賴 python2 的東西.
因此我的習慣是
盡可能地使用 python 版本控制工具.
盡可能地不要影響電腦的 global 環境.
讓套件跟著專案走, 而不是跟著 python 版本走,
避免專案 A 要用 requests-1 版本,
專案 B 要用 requests-2 版本…
版本好切換操作, 環境不要爆炸
pyenv
pyenv
是用來管理 OS 環境的 Python 版本,
# 用 homebrew 安裝
brew install pyenv
pyenv 配置在 zsh 環境
這幾行會在 ~/.zshrc
裡面添加 PYENV_ROOT
這些環境變數,
還有在 zsh 啟動時執行 pyenv init
.
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
安裝完我習慣重新載入 ~/.zshrc
, 先驗證一下 ~/.zshrc 有沒有改壞, 然後按照官方建議的重啟 shell 環境.
# 驗證一下有沒有 error, 基本上就能 echo $PYENV_ROOT 這個環境變數了
source ~/.zshrc
# 官方建議的重啟 shell 環境.
exec "$SHELL"
pyenv 常用指令
# pyenv 目前版本
pyenv --version
# 目前安裝的 python 版本
pyenv versions
# 列出可安裝的 python 版本, 實在眼花撩亂啊
pyenv install -l | grep '你要的版本'
# 安裝 Cpython 3.13.0 並且 output 一些額外的資訊
# 安裝完會在 ~/users/yourname/.pyenv/versions 看到你安裝的 python 版本
# 而上面 zshrc 的設定, 會載入 ~/users/yourname/.pyenv/shims 裡面的 bin
pyenv install -v 3.13.0
# 切換 local 版本, 會在當下資料夾產生一個 `.python-version`
# 類似 nvm 的 .nvmrc 裡面只會有一行註記版本號
pyenv local '你要的版本'
# 切換 global 的版本, 也就是在不同的 zsh terminal 都會是這個 python 版本
pyenv global '你要的版本'
# 解除 Cpython 3.13.0
pyenv uninstall 3.13.0
pip
用 pyenv 安裝完 python, 通常就會有 pip 這工具, 我不確定是不是 python bundle?
沒有的話參考 guides
# 確認一下目前運行的 python 環境
pyenv which python
/Users/username/.pyenv/versions/3.13.0/bin/python
# 確認 python3 的 pip (跟 python 版本綁定)
python3 -m pip --version
pip 24.2 from /Users/username/.pyenv/versions/3.13.0/lib/python3.13/site-packages/pip (python 3.13)
# 沒有的話, 執行這個安裝 pip 並升級,
# -m: 表要以模組形式執行, 這裡是執行 pip 模組
# --upgrade 升級
python3 -m pip install --upgrade pip
pip 的依賴安裝去哪裡了?
NodeJs 的開發者, 應該很容易理解 pip 就類似 pnpm 或是 npm 的工具.
但 pip 可能是 bundle 的關係, 所以都安裝在 python 版本資料夾內
# 安裝 http requests 依賴.
pip install requests
# 確認 requests 安裝到哪裡了
pip show requests
Name: requests
Version: 2.32.3
Summary: Python HTTP for Humans.
Home-page: https://requests.readthedocs.io
Author: Kenneth Reitz
Author-email: me@kennethreitz.org
License: Apache-2.0
# 底下這行, 說明是安裝到 /3.13.0/lib 這個目錄底下...
Location: /Users/username/.pyenv/versions/3.13.0/lib/python3.13/site-packages
# requests 的依賴
Requires: certifi, charset-normalizer, idna, urllib3
Required-by:
那這樣的話可能會有一些問題
套件依賴無法跟著專案版控,
套件依賴的版本號, 可能會隨著時間不同, 導致 install 的當下拉到不同的版本.
venv
venv 是用來建立 python 虛擬環境的, 似乎也是 python 的 bundle?
# 進入 project 資料夾
cd your-project
# 會在專案資料夾下產生 .venv 的資料夾,
# .venv 也可替換成比較容易理解的版號 (.3.13.0)
# 一個專案可以產生多個 venv 環境, 這在測試階段可能很有用.
python3 -m venv .venv
# 在 CLI 啟用 venev 的 python 環境
# 吃的會是執行指令當下指定的 .venv 內的 python3 環境
source .venv/bin/activate
# 也可以改為用 3.13.0 的環境 (A/B testing ?)
# source .3.13.0/bin/activate
# 確認 python 環境
which python3
# 這邊顯示的就不是 pyenv 的 python3 了
/Users/username/projects/your-project/.venv/bin/python3
# 確認 pip 環境
which pip
/Users/username/projects/your-project/.venv/bin/pip
# 安裝 requests
pip install requests
# 確認 requests 安裝位置
pip show requests
Name: requests
Version: 2.32.3
Summary: Python HTTP for Humans.
Home-page: https://requests.readthedocs.io
Author: Kenneth Reitz
Author-email: me@kennethreitz.org
License: Apache-2.0
# 路徑變成專案底下的 .venv/lib/python3.9
Location: /Users/username/projects/your-project/.venv/lib/python3.9/site-packages
Requires: certifi, charset-normalizer, idna, urllib3
Required-by:
# 解除現在 venv 的 python 環境
deactivate
# 確認 python 環境
pyenv which python
/Users/yourname/.pyenv/versions/3.13.0/bin/python3
這樣已經達成我第一個目標, 讓專案有各自的 python 環境. 但也有一些缺點.
.venv / .3.13.0 不會被版控, 內有設定
.gitignore
檔案.因為 .venv / .3.13.0 無法被 git pull 就表示, 其他 team member 需要自己安裝, 就有可能安裝到不同的套件版本.
延伸上面問題, 跑 CI/CD 流程的時候該怎麼辦?
Poetry
安裝依賴 pipx, pipx 類似 nodejs 的 npx 工具, 可以安裝或是直接執行套件來初始專案.
雖然可以透過 pip 安裝 poetry, 但 pip 跟你執行當下的 python 環境 bundle, 透過 pip 安裝的話, 就會在 ~/.pyenv/versions/3.13.0/lib/python3.13/site-packages
, 這會導致 python 版本切換而無法使用 poetry, 所以建議還是用 pipx 來安裝 poetry.
# 查詢 poetry
pip show poetry
Name: poetry
Version: 1.8.4
Summary: Python dependency management and packaging made easy.
Home-page: https://python-poetry.org/
Author: Sébastien Eustace
Author-email: sebastien@eustace.io
License: MIT
Location: /Users/yourname/.pyenv/versions/3.13.0/lib/python3.13/site-packages
Requires: build, cachecontrol, cleo, crashtest, dulwich, fastjsonschema, installer, keyring, packaging, pexpect, pkginfo, platformdirs, poetry-core, poetry-plugin-export, pyproject-hooks, requests, requests-toolbelt, shellingham, tomlkit, trove-classifiers, virtualenv, xattr
Required-by: poetry-plugin-export
pipx
# hombrew 安裝
brew install pipx
# 自動設定環境變數, 等同於在 zsh 環境添加
# export PATH="$PATH:/Users/yourname/.local/bin"
# ~/.local/bin 就是 pipx 工作資料夾
pipx ensurepath
使用上跟 pip 差不多, 更多細節看官方文件, 或是 pipx --help
就可以了.
使用 pip 安裝的套件會位於 ~/.local/pipx/venvs
# 列出本地套件清單, 會顯示下面資訊
pipx list
# 在 ~/.local/pipx/ 裡面有 venvs 的目錄, 還有操作手冊說明
# 執行 list 的時候, 我已經安裝了 poetry.
venvs are in /Users/yourname/.local/pipx/venvs
apps are exposed on your $PATH at /Users/yourname/.local/bin
manual pages are exposed at /Users/yourname/.local/share/man
package poetry 1.8.4, installed using Python 3.13.0
- poetry
使用上跟 pip 差不多, 更多細節看官方文件, 或是 pipx --help
就可以了.
install:安裝一個套件
install-all:安裝所有套件
uninject:從現有的虛擬環境中卸載已注入的套件
inject:將套件安裝到現有的虛擬環境中
pin:鎖定指定的套件,防止其被升級
unpin:取消鎖定指定的套件
upgrade:升級一個套件
upgrade-all:升級所有套件。對每個套件運行 pip install -U <pkgname>
upgrade-shared:升級共享庫
uninstall:卸載一個套件
uninstall-all:卸載所有套件
reinstall:重新安裝一個套件
reinstall-all:重新安裝所有套件
list:列出已安裝的套件
interpreter:與由 pipx 管理的解釋器進行交互
run:下載套件的最新版本到臨時虛擬環境中,然後從中運行應用。也兼容本地的 __pypackages__ 目錄(實驗性功能)
runpip:在已存在的 pipx 管理的虛擬環境中運行 pip
ensurepath:確保 pipx 運行所需的目錄已加入到 PATH 環境變量中
environment:列出 pipx 使用的環境變量和路徑
completions:顯示啟用 shell 自動補全功能的說明
在研究 pipx 的東西還有許多細節, 改天有空再整理.
用 pipx 安裝 poetry
pipx install poetry
在 zsh 環境設定指令自動補齊, 我的 zsh 環境有安裝 oh-my-zsh
, 所以整理在 plugins 裏面.
mkdir $ZSH_CUSTOM/plugins/poetry
poetry completions zsh > $ZSH_CUSTOM/plugins/poetry/_poetry
安裝完記得到 ~/.zshrc
配置好 plugins.
# Which plugins would you like to load?
# Standard plugins can be found in $ZSH/plugins/
# Custom plugins may be added to $ZSH_CUSTOM/plugins/
# Example format: plugins=(rails git textmate ruby lighthouse)
# Add wisely, as too many plugins slow down shell startup.
plugins=(
...
...
poetry
)
poetry 產生專案
poetry new poetry-demo
產生的專案結構如下, 對 python 新手還滿友善的.
其中 pyproject.toml
檔案, 類似 package.json
的感覺, 裡面就是專案資訊, 跟專案套件依賴相關描述了.
# 安裝依賴的前置條件就是要到專案目錄底下
cd python-poetry
# 安裝依賴, pendulum (python 的 local, date, time 處理套件)
poetry add pendulum
然後就爆炸了, 我是 python 新手, 所以就胡亂 google 問 AI.
maturing 看起來是 https://github.com/PyO3/maturin 這個用來產生 cargo 專案, 且其中一行描述了 Cargo meta 需要設置在環境變數 PATH 裏面, 我確實沒有.
AI 建議我降版, 或是安裝 Cargo.
Package operations: 1 install, 0 updates, 0 removals
- Installing pendulum (3.0.0): Failed
ChefBuildError
Backend subprocess exited when trying to invoke build_wheel
Running `maturin pep517 build-wheel -i /private/var/folders/7y/khgfhgl11d52pv2x7fk6t8wm0000gn/T/tmpwrk1p383/.venv/bin/python --compatibility off`
💥 maturin failed
Caused by: Cargo metadata failed. Do you have cargo in your PATH?
Caused by: No such file or directory (os error 2)
Error: command ['maturin', 'pep517', 'build-wheel', '-i', '/private/var/folders/7y/khgfhgl11d52pv2x7fk6t8wm0000gn/T/tmpwrk1p383/.venv/bin/python', '--compatibility', 'off'] returned non-zero exit status 1
at ~/.local/pipx/venvs/poetry/lib/python3.13/site-packages/poetry/installation/chef.py:164 in _prepare
160│
161│ error = ChefBuildError("\n\n".join(message_parts))
162│
163│ if error is not None:
→ 164│ raise error from None
165│
166│ return path
167│
168│ def _prepare_sdist(self, archive: Path, destination: Path | None = None) -> Path:
Note: This error originates from the build backend, and is likely not a problem with poetry but with pendulum (3.0.0) not supporting PEP 517 builds. You can verify this by running 'pip wheel --no-cache-dir --use-pep517 "pendulum (==3.0.0)"'.
我在想這可能是個時機不好的測試案例 XD, 索性就放棄官方的 pendulum 案例, 改裝 flask 就成功了.
poetry add flask
測試了一下 pendulum 用 poetry 安裝有許多問題, 但因為太菜了, 暫時沒能力深入學習.
感覺 pendulum 是個生機蓬勃的套件 XD, 有點亂啊.
總結
Python 的環境配置與依賴管理真的是個門檻, 但語法滿容易學習的.
如果是實際專案的話, 應該還是要按照專案規劃配置環境.
但這是我自己學習的紀錄, 我傾向於
先用 pyenv 安裝管理 OS 層的 python.
用 pipx 控制管理 OS 層的 python 依賴.
用 poetry 控制管理專案內的 python 環境與依賴.
Thx and Ref
內有完整的 poetry 學習 https://blog.kyomind.tw/python-poetry/
高建龍, 內有完善的 python 語法學習 https://pythonbook.cc/chapters/basic/install-python#%E4%BD%BF%E7%94%A8-poetry