一:pyenv介紹
pyenv lets you easily switch between multiple versions of Python. It's simple, unobtrusive, and follows the UNIX tradition of single-purpose tools that do one thing well.
簡單的說,pyenv 可以根據需求使用戶在系統里安裝和管理多個 Python 版本:
-
配置當前用戶的python的版本
-
配置當前shell的python版本
-
配置某個項目(目錄及子目錄)的python版本
-
配置多個虛擬環境
二:工作原理介紹
pyenv是利用系統環境變量PATH的優先級,劫持python的命令到pyenv上,根據用戶所在的環境或目錄,使用不同版本的python。
how it works:
At a high level, pyenv intercepts Python commands using shim executables injected into your PATH, determines which Python version has been specified by your application, and passes your commands along to the correct Python installation.
對於系統環境變量 PATH ,里面包含了一串由冒號分隔的路徑,例如 /usr/local/bin:/usr/bin:/bin。每當在系統中執行一個命令時,例如 python 或 pip,操作系統就會在 PATH 的所有路徑中從左至右依次尋找對應的命令。因為是依次尋找,因此排在左邊的路徑具有更高的優先級。在PATH 最前面插入一個 $(pyenv root)/shims 目錄,$(pyenv root)/shims目錄里包含名稱為python以及pip等可執行腳本文件;當用戶執行python或pip命令時,根據查找優先級,系統會優先執行shims目錄中的同名腳本。pyenv 正是通過這些腳本,來靈活地切換至我們所需的Python版本。
更詳細的資料,可以查看pyenv的文檔介紹或者源碼實現。
三:pyenv的安裝
系統環境:CentOS 6.10
1.安裝依賴環境
yum
-y
install
gcc
zlib-devel
bzip2
-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel git
2.安裝pyenv包
pyenv可以通過多種方式安裝,可以參考項目在github上的Installtion。推薦采用The automatic installer的方式安裝,可以一鍵安裝pyenv的所有插件。
The automatic installer
Visit my other project: https://github.com/pyenv/pyenv-installer
一鍵安裝:
分析一下上面的pyenv-installer腳本,可以發現在centos上,其實它做了以下事情:
git clone
--depth
1
"
git://github.com/pyenv/pyenv-doctor.git
"
"
${HOME}/.pyenv/plugins/pyenv-doctor
"
git clone
--depth
1
"
git://github.com/pyenv/pyenv-installer.git
"
"
${HOME}/.pyenv/plugins/pyenv-installer
"
git clone
--depth
1
"
git://github.com/pyenv/pyenv-update.git
"
"
${HOME}/.pyenv/plugins/pyenv-update
"
git clone
--depth
1
"
git://github.com/pyenv/pyenv-virtualenv.git
"
"
${HOME}/.pyenv/plugins/pyenv-virtualenv
"
git clone
--depth
1
"
git://github.com/pyenv/pyenv-which-ext.git
"
"
${HOME}/.pyenv/plugins/pyenv-which-ext
"
3.pyenv安裝完成
安裝完成后,還需要執行下面的命令,將pyenv安裝到系統環境變量中。
echo 'export PATH="/home/python/.pyenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bash_profile
source ~/.bash_profile
#查看pyenv版本
pyevn -v
#更新pyenv
pyenv update
四:pyenv的使用
$
pyenv help
Usage: pyenv
<command> [<args>
]
Some useful pyenv commands are:
commands List all available pyenv commands
local Set or show the local application
-
specific Python version
global Set or show the global Python version
shell Set or show the shell
-
specific Python version
install
Install a Python version using python-
build
uninstall Uninstall a specific Python version
rehash Rehash pyenv shims (run this after installing executables)
version Show the current Python version and its origin
versions List all Python versions available to pyenv
which
Display the full path to an executable
whence List all Python versions that contain the given executable
See `pyenv help
<command>
'
for information on a specific command.
1.使用pyen安裝python
使用 pyenv install --list 查看可以安裝的python版本,pyenv install <version> 安裝python,可以使用-v參數,查看安裝過程。更多詳細信息,使用 python install help命令了解
$pyenv install --help
Usage: pyenv install [-f] [-kvp] <version>
pyenv install [-f] [-kvp] <definition-file>
pyenv install -l|--list
pyenv install --version
-l/--list List all available versions
-f/--force Install even if the version appears to be installed already
-s/--skip-existing Skip if the version appears to be installed already
python-build options:
-k/--keep Keep source tree in $PYENV_BUILD_ROOT after installation
(defaults to $PYENV_ROOT/sources)
-p/--patch Apply a patch from stdin before building
-v/--verbose Verbose mode: print compilation status to stdout
--version Show version of python-build
-g/--debug Build a debug version
For detailed information on installing Python versions with
python-build, including a list of environment variables for adjusting
compilation, see:
https://github.com/pyenv/pyenv#readme
$ pyenv install --list
Available versions:
2.1.3
2.2.3
2.3.7
………………
$ pyenv install 3.6.4
Downloading Python-3.6.4.tar.xz...
Installing Python-3.6.4...
Installed Python-3.6.4 to /home/python/.pyenv/versions/3.6.4
$ pyenv install 3.5.4
Downloading Python-3.5.4.tar.xz...
Installing Python-3.5.4...
Installed Python-3.5.4 to /home/python/.pyenv/versions/3.5.4
2.查看使用的python版本
參數 versions,可以查看pyenv已經安裝及可管理python版本,前面帶星號(*)表示當前使用的版本;也可以使用version查看當前使用的版本
#查看可使用的版本,前面帶*
表示當前使用的版本
pyenv versions
#查看當前使用的版本
pyenv version
$ pyenv versions
* system (set by /home/python/.pyenv/version)
3.5.4
3.6.4
$ pyenv version
system (set by
/home/python/.pyenv/version)
3.配置及管理python版本
pyenv管理python版本的三個基礎命令
-
pyenv global <version>
-
pyenv shelll <version>
-
pyenv local <version>
1)使用pyenv global <version>配置當前用戶的系統使用的python版本
$ pyenv versions
*
system
3.5.4
3.6.4 (set by /home/python/.pyenv/
version)
$ python -V
Python 2.6.6
$ pyenv global 3.6.4
$ pyenv versions
system
3.5.4
* 3.6.4 (set by /home/python/.pyenv/
version)
$ python -V
Python 3.6.4
$ python -V
Python 3.6.4
$ exit
logout
#重新登錄
$ python -V
Python 3.6.4
2)使用pyenv shelll <version>配置當前shell的python版本,退出shell則失效
查看當前的python版本及可用版本
$ python -V
Python 2.6.6
$ pyenv versions
* system (set by /home/python/.pyenv/
version)
3.5.4
3.6.4
使用pyenv shell <version>命令配置當前shell的python版本
$ pyenv shell 3.5.4
查看配置以后的python版本
$ python -V
Python 3.5.4
$ pyenv versions
system
* 3.5.4
(set by PYENV_VERSION environment variable)
3.6.4
當前shell下,取消配置的使用python shell --unset;若退出此shell,配置也會失效。
$ pyenv shell --unset
3)使用pyenv local <version>配置所在項目(目錄)的python版本
新建一個文件夾~/project,在此文件夾下使用python local <version>
$ mkdir project
$ cd project
$ pyenv local 3.6.4
在此文件夾下,查看版本
$ pyenv versions
system
3.5.4
* 3.6.4 (set by /home/python/project/.python-
version)
$ python -V
Python 3.6.4
新建目錄~/project/p_a,切換到~/project/p_a,並查看版本
$ mkdir p_a&& cd p_a
$ python -V
Python 3.6.4
$ pyenv versions
system
3.5.4
* 3.6.4 (set by /home/python/project/.python-version)
新建目錄~/project/p_b,切換到~/project/p_b,使用pyenv local system,並查看版本
$ mkdir ../p_b&& cd ../p_b
$ pyenv local system
$ python -V
Python 2.6.6
$ pyenv versions
* system (set by /home/python/project/p_b/.python-version)
3.5.4
3.6.4
4.稍微深入一下,pyenv是如何進行python版本管理的
使用which命令,可以看到,python命令已經不是本來的python命令,而是shims中的腳本文件
$ which python
~/.pyenv/shims/
python
$ which python3
~/.pyenv/shims/
python3
$ which pip3
~/.pyenv/shims/pip3
查看~/.pyenv/shims/python,可以看到python的命令最終被~/
.pyenv/libexec/pyenv接管運行,感興趣的同學可以接着看
~/
.pyenv/libexec/pyenv代碼的實現,這里就不從代碼上分析了。
#!/usr/bin/env
bash
set -
e
[ -n "$PYENV_DEBUG" ] && set -
x
program="${0##*/}"
if [[ "$program" = "python"* ]]; then
for arg; do
case "$arg" in
-c* | --
) break ;;
*/* )
if [ -f "$arg" ]; then
export PYENV_FILE_ARG="$arg"
break
fi
;;
esac
done
fi
export PYENV_ROOT="/home/python/.pyenv"
exec "/home/python/.pyenv/libexec/pyenv" exec "$program" "$@"
pyenv的文檔,對此是如此介紹的:
pyenv works by inserting a directory of shims at the front of your PATH:
$(pyenv root)/shims:/usr/local/bin:/usr/bin:/bin
Through a process called rehashing, pyenv maintains shims in that directory to match every Python command across every installed version of Python—python, pip, and so on.
Shims are lightweight executables that simply pass your command along to pyenv. So with pyenv installed, when you run, say, pip, your operating system will do the following:
Search your PATH for an executable file named pip
Find the pyenv shim named pip at the beginning of your PATH
Run the shim named pip, which in turn passes the command along to pyenv
Choosing the Python Version
When you execute a shim, pyenv determines which Python version to use by reading it from the following sources, in this order:
The PYENV_VERSION environment variable (if specified). You can use the pyenv shell command to set this environment variable in your current shell session.
The application-specific .python-version file in the current directory (if present). You can modify the current directory's .python-version file with the pyenv local command.
The first .python-version file found (if any) by searching each parent directory, until reaching the root of your filesystem.
The global $(pyenv root)/version file. You can modify this file using the pyenv global command. If the global version file is not present, pyenv assumes you want to use the "system" Python. (In other words, whatever version would run if pyenv weren't in your PATH.)
NOTE: You can activate multiple versions at the same time, including multiple versions of Python2 or Python3 simultaneously. This allows for parallel usage of Python2 and Python3, and is required with tools like tox. For example, to set your path to first use your system Python and Python3 (set to 2.7.9 and 3.4.2 in this example), but also have Python 3.3.6, 3.2, and 2.5 available on your PATH, one would first pyenv install the missing versions, then set pyenv global system 3.3.6 3.2 2.5. At this point, one should be able to find the full executable path to each of these using pyenv which, e.g. pyenv which python2.5 (should display $(pyenv root)/versions/2.5/bin/python2.5), or pyenv which python3.4 (should display path to system Python3). You can also specify multiple versions in a .python-version file, separated by newlines or any whitespace.
大概的意思是說,當使用的python命令被pyenv接管以后,到底使用哪個python版本,是由下面這些信息依次決定的:
-
如果PYENV_VERSION這個變量否存在,則使用這個變量里的版本;這個變量是由pyenv shell <version>配置的;
-
按照往父目錄查找的順序查找直到根目錄,第一個被查找到的.python-version文件作為版本文件,其指定的版本作為使用的python版本;這個文件使用pyenv local <version>配置
-
$(pyenv root)/version 這個文件若存在,則使用這個文件里制定的版本作為python版本;若不存在,則使用系統的版本;這個文件使用pyenv global <version>配置
-
如果以上變量或文件都沒有找到,就按照系統默認制定的python版本了。
另外,用戶還可以在一個環境下同時配置多個版本的python;具體的解釋和用法,可以參考文檔。
回頭再看一下上面pyenv versions命令,輸出的結果中會有一個set by的提示,也向用戶展示了,pyenv是基於什么指定的python版本。
五:python的虛擬環境
為了對不同的項目進行隔離,使每個項目使用獨立的解釋器及依賴,需要配置python虛擬環境。本機已經安裝了pyenv-virtualenv
使用pyenv install安裝的python版本,比如3.6.4;解釋器安裝的路徑為~/.pyenv/versions/3.6.4/;插件的安裝的路徑為~/.pyenv/versions/3.6.4/lib/python3.6/site-packages;
使用pyenv-virtualenv創建python虛擬環境,實質上是在~/.pyenv/versions/3.6.4/下創建一個文件夾evns,存放該虛擬環境python的解釋器;並且在~/.pyenv/下創建一個軟連接,該虛擬環境可以通過pyenv進行管理;
$ pyenv virtualenv 3.6.4 my_3.6.4
Requirement already satisfied: setuptools in /home/python/.pyenv/versions/3.6.4/envs/my_3.6.4/lib/python3.6/site-packages
Requirement already satisfied: pip in /home/python/.pyenv/versions/3.6.4/envs/my_3.6.4/lib/python3.6/site-packages
$ll ~/.pyenv/versions/
total 8
drwxr-xr-x 6 python python 4096 Jul 20 00:59 3.5.4
drwxr-xr-x 7 python python 4096 Jul 21 01:03 3.6.4
lrwxrwxrwx 1 python python 48 Jul 21 01:03 my_3.6.4 -> /home/python/.pyenv/versions/3.6.4/envs/my_3.6.4
查看python虛擬環境
$ pyenv virtualenvs
3.6.4/envs/my_3.6.4 (created from /home/python/.pyenv/versions/3.6.4)
my_3.6.4 (created from /home/python/.pyenv/versions/3.6.4)
切換到python虛擬環境
$ pyenv shell my_3.6.4
(my_3.6.4) [python@localhost 3.6.4]$
(my_3.6.4) [python@localhost 3.6.4]$ pyenv versions
system
3.5.4
3.6.4
3.6.4/envs/my_3.6.4
* my_3.6.4 (set by PYENV_VERSION environment variable)