pythonではpyenvというツールを使うことで、1台のPCに複数バージョンのpython環境を共存させることができます。
pyenvは非常に便利なツールなのですが、仕組みがわかっていないと思った通りにバージョン切り替えを行えなかったりトラブルを生んでしまうことがあります。そこで、今回はpyenvの仕組みを確認してみました。
環境の確認
作業を始める前に、現在の環境を確認しておきます。
OSはAmazonLinuxになっていますが、実際はvagrant上でmvbcoding/awslinuxのboxを実行しています。
$ python --version
Python 2.7.12
$ which python
/usr/bin/python
$ more /etc/system-release
Amazon Linux AMI release 2017.03
pyenvのインストール
まずは、pyenvをインストールします。pyenvはgitからcloneするだけでインストールできます。
sudo yum install gcc gcc-c++ make git openssl-devel bzip2-devel zlib-devel readline-devel sqlite-devel -y
cd ~
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
pyenv自体がインストールできたか確認をかねて、pyenvのバージョンを確認します。本来ならここで~/.pyenv/binにPATHを通すところですが、今回は仕組みを把握するためにあえてPATHの設定を行わずに作業を進めます。
$ ~/.pyenv/bin/pyenv --version
pyenv 1.2.4
pyenv
をオプションなしで実行すると、pyenvのヘルプが表示されます。
$ ~/.pyenv/bin/pyenv
pyenv 1.2.4
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.
For full documentation, see: https://github.com/pyenv/pyenv#readme
pyenv install -l
でインストール可能なpythonのバージョン一覧を確認します。背選択肢は非常に多くあり、python2系、3系の選択だけでなくanacondaなどもインストールすることができることが確認できます。
$ ~/.pyenv/bin/pyenv install -l
Available versions:
2.1.3
2.2.3
...
2.7.14
2.7.15
3.0.1
3.1
3.1.1
...
3.6.4
3.6.5
3.7.0b3
3.7-dev
3.8-dev
activepython-2.7.14
activepython-3.5.4
activepython-3.6.0
anaconda-1.4.0
anaconda-1.5.0
...
stackless-3.4.2
stackless-3.4.7
stackless-3.5.4
他のバージョンのpythonをインストールしてみる
pyenv install
コマンドで複数のバージョンのpythonをインストールしてみます。
今回は、動作確認を兼ねてPython3系と2系の最新版だった3.6.5と2.7.15をインストールしてみました。
$ ~/.pyenv/bin/pyenv install 3.6.5
Downloading Python-3.6.5.tar.xz...
-> https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tar.xz
Installing Python-3.6.5...
Installed Python-3.6.5 to /home/vagrant/.pyenv/versions/3.6.5
$ /home/vagrant/.pyenv/bin/pyenv install 2.7.15
Downloading Python-2.7.15.tar.xz...
-> https://www.python.org/ftp/python/2.7.15/Python-2.7.15.tar.xz
Installing Python-2.7.15...
Installed Python-2.7.15 to /home/vagrant/.pyenv/versions/2.7.15
インストールしたpythonの環境は.pyenv/versionsに展開されています。lsコマンドでインストールできたかを確認できます。
$ ls ~/.pyenv/versions/
2.7.15/ 3.6.5/
インストールしたバージョンにpythonを切り替えてみる
pyenv install
を実行しただけでは、pythonのバージョンは切り替わりません
$ which python
/usr/bin/python
$ python --version
Python 2.7.12
pyenvが管理しているバージョンはversions
で確認できます。「*」がついた行が現在の環境です。
$ ~/.pyenv/bin/pyenv versions
* system (set by /home/vagrant/.pyenv/version)
3.6.5
2.7.15
pyenv global
コマンドで、バージョンを切り替えてみます。
オプションにglobalとあるので、システム全体の設定が切り替わりそうに見えますが、実際は実行しているユーザの環境のみに影響を与えます。
$ ~/.pyenv/bin/pyenv global 3.6.5
$ ~/.pyenv/bin/pyenv versions
system (set by /home/vagrant/.pyenv/version)
* 3.6.5
2.7.15
これによってpythonのバージョンが変わるかと思ったら、まだ変わりません。
$ which python
/usr/bin/python
$ python --version
Python 2.7.12
ここで初めてパスを通します。
echo 'export PYENV_ROOT="$HOME/.pyenv"
echo 'export PATH="$PYENV_ROOT/bin:$PATH"
パスを通したことによって、pyenv
コマンドはパス指定なしで実行できるようになりました
$ which pyenv
~/.pyenv/bin/pyenv
$ pyenv --version
pyenv 1.2.4
ですが、pythonのバージョンはまだ変わっていません
$ which python
/usr/bin/python
$ python --version
Python 2.7.12
次に、下記のコマンドを実行してみます。
$ eval "$(pyenv init -)"
するとpythonのバージョンが切り替わりました。
$ python --version
Python 3.6.5
実行されているpythonコマンドのパスもpyenv initによって変更されています。
[vagrant@localhost ~]$ which python
~/.pyenv/shims/python
以上の実験で、pyenv init
コマンドによってpythonの実行パスが差し替えられることがわかりました。
仕組みとしてはeval "$(pyenv init -)"
で環境変数PATHに.pyenv/shims
を追加し、pyenv global
やpyenv local
で該当バージョンのpythonを.pyenv/shimsにコピーしているようです。
pyenv initが行なっていることを確認する
pyenv initが内部で何を行なっているかは、$(pyenv init -)
の結果をechoすることで確認できます。
$ echo "$(pyenv init -)"
export PATH="/home/vagrant/.pyenv/shims:${PATH}"
export PYENV_SHELL=bash
source '/home/vagrant/.pyenv/libexec/../completions/pyenv.bash'
command pyenv rehash 2>/dev/null
pyenv() {
local command
command="${1:-}"
if [ "$#" -gt 0 ]; then
shift
fi
case "$command" in
rehash|shell)
eval "$(pyenv "sh-$command" "$@")";;
*)
command pyenv "$command" "$@";;
esac
}
再度バージョンを切り替える
pyenv local
コマンドでpythonのバージョンを2.7.15に切り替えてみます。
$ pyenv local 2.7.15
pyenv versions
コマンドでバージョンが切り替わったのを確認します。
$ pyenv versions
system
* 2.7.15 (set by /home/vagrant/.pyenv/shims/.python-version)
3.6.5
再度バージョンを確認すると2.7.15に切り替わったことがわかります。pythonの実行パスは~/.pyenv/shims/のままです。
$ python --version
Python 2.7.15
$ which python
~/.pyenv/shims/python
簡単にpyenvを使えるようにしておく
最後に、次回以降もpyenvを簡単に使えるよう、自動で環境変数をセットするように.bash_profileを変更しておきます。.bash_profileの内容はLinuxログインするたびに実行されるので、毎回export, evalコマンドを実行しなくてもよくなります。
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
この方法でインストールしたpyenvはどうやってアンインストールすれば
ようのでしょうか。
普通にやる
pip unistall pyenv