python多版本管理
背景
python2.x 已經(jīng)停止維護(hù),日常開發(fā)中一般都使用 python3.x 的版本,然而考慮到部分舊的腳本是用 python2.x 寫的,因此同時在機(jī)器上維護(hù)多份不同的 python 版本是非常常見的現(xiàn)象。那么如何更好地管理和切換不同的 python 版本便成了一個有待解決的問題?
經(jīng)常被多個版本困擾的我,今天好好查閱了一番,發(fā)現(xiàn) pyenv 是一個不錯的選擇,現(xiàn)將相關(guān)內(nèi)容記錄如下,以供查閱。
備注: 筆者使用的是MacOS,所以后續(xù)操作均基于MacOS。
安裝pyenv
pyenv 是一個 python 版本管理工具,具備方便、快捷地安裝、管理多個 python 版本,并在不同 python 版本間進(jìn)行切換的能力。
安裝pyenv
使用 homebrew 安裝 pyenv,在終端中輸入如下命令,該命令會自動下載最新版本的 pyenv,并自動下載依賴包。
brew install pyenv
安裝完成后,可運(yùn)行which pyenv命令查看pyenv是否存在。
pyenv工作原理
pyenv 會在系統(tǒng)環(huán)境變量 PATH 前面插入一個墊片目錄 (pyenv root)/shims,這樣每當(dāng)運(yùn)行 python 命令時,pyenv 便會攔截到該命令,并調(diào)用當(dāng)前環(huán)境下使用的 python 版本對應(yīng)的該命令。
通過重新哈希,pyenv 會在目錄中維護(hù)一個 shims,從而將每一個 python 命令映射為不同 python 版本下的相應(yīng)命令。
shim 是一個輕量級的可執(zhí)行文件,它的主要任務(wù)是將終端輸入的 python 命令傳遞給 pyenv。
在安裝有 pyenv 的機(jī)器上,輸入 python 命令時(如pip),操作系統(tǒng)會執(zhí)行如下操作:
- 在 PATH 指向的目錄中查找名為 pip 的可執(zhí)行文件;
- 在 PATH 起始位置找到名為 pip 的 pyenv shim;
- 運(yùn)行名為 pip 的 shim,以告知 pyenv 運(yùn)行的 python 命令;
- pyenv 查找當(dāng)前環(huán)境對應(yīng)的 python 版本中的 pip 命令,并運(yùn)行。
為了在每次啟動 shell 的時候都能自動將 python 墊片目錄添加到 PATH 前面,可在/.bash_profile(或/.zshrc)末尾添加如下命令,在終端執(zhí)行如下命令即可:
# 檢測 pyenv 是否存在,若存在,則執(zhí)行 pyenv init 命令
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
更新pyenv
brew upgrade pyenv
卸載pyenv
如果只是暫時不想使用 pyenv 的話,可考慮將/.bash_profile(或/.zshrc)文件中的pyenv init命令注釋掉,這樣可隨時通過取消注釋開啟 pyenv 功能。
如果想完全卸載 pyenv,則可按如下步驟操作:
# 刪除 pyenv 根目錄,同時會將所有安裝在$(pyenv root)/versions/目錄下的 python 版本刪除
rm -rf $(pyenv root)
# 卸載 pyenv
brew uninstall pyenv
pyenv常用命令
pyenv 常用命令可在Command Reference查詢。
pyenv commands
列出所有可用的pyenv命令。
$ pyenv commands
--version
commands
completions
exec
global
help
hooks
init
install
local
pyenv install
安裝指定 python 版本,通過 python-build命令安裝。
# 列出所有可用的版本
pyenv install -l
pyenv install --list
$ pyenv install -l
Available versions:
2.1.3
2.2.3
2.3.7
2.4.0
2.4.1
2.4.2
2.4.3
# 安裝指定 python 版本
pyenv install [-f] [-kvp] <version>
# 選項說明
-f/--force: 強(qiáng)制安裝,即使該版本已經(jīng)安裝過了
-v/--verbose: 輸出安裝過程中的詳細(xì)信息
-g/--debug: 構(gòu)建 debug 版本
-s/--skip-existing: 跳過已安裝的版本
# 安裝 python 3.8.2
$ pyenv install 3.8.2
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.8.2.tar.xz...
-> https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz
Installing Python-3.8.2...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.8.2 to /Users/Lilac/.pyenv/versions/3.8.2
pyenv uninstall
卸載指定 python 版本。
# 卸載指定 python 版本
pyenv uninstall [-f|--force] <version>
# 選項說明
-f/--force: 強(qiáng)制卸載,當(dāng)待卸載版本存在時,無需確認(rèn),當(dāng)待卸載版本不存在時,不顯示錯誤信息
# 卸載 python 3.8.2
$ pyenv uninstall 3.8.2
pyenv: remove /Users/Lilac/.pyenv/versions/3.8.2? y
$ pyenv versions
system
3.7.0
pyenv local
設(shè)置當(dāng)前工作目錄下的 python 版本。
pyenv local命令執(zhí)行后會在當(dāng)前工作目錄下的.python-version文件中寫入設(shè)入的 python 版本。
在當(dāng)前工作目錄執(zhí)行 python 命令時,會優(yōu)先使用pyenv local命令指定的 python 版本。
# 設(shè)置當(dāng)前工作目錄下用 python3.8.2
$ pyenv local 3.8.2
# 重置當(dāng)前目錄的 python 版本
$ pyenv local --unset
# 同時設(shè)置多個當(dāng)前工作目錄可用的 python 版本,如 python2.7.16 和 python3.8.2
# 注意:此時會優(yōu)先使用 python2.7.16
$ pyenv local 2.7.16 3.8.2
# 顯示當(dāng)前 pyenv 支持的 python 版本,該命令后文會介紹
$ pyenv versions
system
* 2.7.16 (set by /Users/Lilac/.python-version)
* 3.8.2 (set by /Users/Lilac/.python-version)
$ python --version
Python 2.7.16
$ python2.7 --version
Python 2.7.16
$ python3.8 --version
Python 3.8.2
pyenv global
設(shè)置全局 python 版本。
pyenv global命令執(zhí)行后會在~/.python-version文件中寫入設(shè)入的 python 版本。
# 示例
# 設(shè)置全局 python 版本為 python3.8.2
$ pyenv global 3.8.2
# 示例
# 同時設(shè)置多個全局 python 版本,如 python2.7.16 和 python3.8.2
# 注意:此時會優(yōu)先使用 python2.7.16
$ pyenv global 2.7.16 3.8.2
$ pyenv versions
system
* 2.7.16 (set by /Users/Lilac/.python-version)
* 3.8.2 (set by /Users/Lilac/.python-version)
$ python --version
Python 2.7.16
$ python2.7 --version
Python 2.7.16
$ python3.8 --version
Python 3.8.2
pyenv shell
設(shè)置當(dāng)前 shell 窗口使用的 python 版本。
實(shí)現(xiàn)方式:通過設(shè)置當(dāng)前 shell 窗口的 PYENV_VERSION 環(huán)境變量實(shí)現(xiàn)。
python版本設(shè)置優(yōu)先級:pyenv shell > pyenv local > pyenv global
即 pyenv 會優(yōu)先使用當(dāng)前 shell 窗口設(shè)置的 python 版本(pyenv shell),如果當(dāng)前窗口未設(shè)置的話,則使用當(dāng)前工作目錄設(shè)置的 python 版本(pyenv local),如果當(dāng)前工作目錄也未設(shè)置,則使用全局 python 版本(pyenv global)。
# 設(shè)置當(dāng)前 shell 窗口 python 版本為2.7.16
$ pyenv shell 2.7.16
# 顯示當(dāng)前 shell 窗口使用的 python 版本
$ pyenv shell
2.7.16
# 重置當(dāng)前 shell 窗口的 python 版本
$ pyenv shell --unset
# 同時設(shè)置多個當(dāng)前 shell 窗口可用的 python 版本,如 python2.7.16 和 python3.8.2
# 注意:此時會優(yōu)先使用 python2.7.16
$ pyenv shell 2.7.16 3.8.2
$ pyenv versions
system
* 2.7.16 (set by PYENV_VERSION environment variable)
* 3.8.2 (set by PYENV_VERSION environment variable)
$ python --version
Python 2.7.16
$ python2.7 --version
Python 2.7.16
$ python3.8 --version
Python 3.8.2
pyenv version
顯示當(dāng)前使用的 python 版本,同時會顯示該版本是如何設(shè)置進(jìn)來的(pyenv global/pyenv local/pyenv shell)。
pyenv version
$ pyenv version
3.8.2 (set by PYENV_VERSION environment variable)
pyenv versions
列出所有 pyenv 已知的 python 版本,當(dāng)前使用的版本會在前面用*號標(biāo)明
pyenv versions
$ pyenv versions
system
3.7.0
* 3.8.2 (set by PYENV_VERSION environment variable)
pyenv rehash
更新墊片目錄 shims 內(nèi)容,以使 pyenv 知道它所管理的 python 版本信息,一般在安裝完一個新版本的 python 后,需運(yùn)行一次該命令。
$ pyenv rehash
pyenv which
顯示當(dāng)前命令的可執(zhí)行文件所在的完整路徑。
pyenv which
$ pyenv which python3
/Users/Lilac/.pyenv/versions/3.8.2/bin/python3