pyenvで複数のPythonバージョンを管理してみよう
pyenv について
pyenvは複数のPythonバージョンを管理するためのツールです、次のような機能があります。
複数バージョンのPythonのインストール
インストールされたPythonバージョンを切り替えて使用
pyenvによる仮想環境の管理と使用
異なるPythonバージョンや仮想環境を自動的に有効化
既にシステムにPythonがインストールされていたとしても、新しいPythonの機能を簡単に試したり、異なるバージョンのPythonを使うことが簡単になるために、pyenvはインストールしておく価値があります。
プロジェクトでシステムPythonを使わない方がよい理由
システムPythonは、OSでインストールされているPythonのことです。もともとインストールされているシステムPython を使わない方がよい理由は、このPythonはオペレーティングシステムが使用するツールであることです。
加えて、システムPython があなたが使用したいバージョンではないかもしれません。例えば、macOS Big Sur (Version 11.8) のシステムPython は 2.7.16 です。
code: zsh
% uname -rsv
Darwin 20.6.0 Darwin Kernel Version 20.6.0: Mon Aug 30 06:12:21 PDT 2021; root:xnu-7195.141.6~3/RELEASE_X86_64
% which python
/usr/bin/python
% python -V
Python 2.7.16
pyenv が行う作業
Pythonのバージョンを簡単かつ柔軟にインストール・管理するためには、次のような作業が必要になります。
ユーザースペースにPythonをビルドしてインストールする
複数のバージョンのPythonをビルドしてインストールする
必要なPythonバージョンを正確に指定する
インストールされたバージョン間の切り替え
pyenv を利用すると、これら全ての作業をとても簡単に行うことができます。
インストール
システム側に必要な要件
Python をビルドするために必要なシステムパッケージ、ライブラリがあり、それらをインストールする必要があります。
これには root権限が必要です。
Ubuntu/Debian
code: bash
$ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev \
libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl
Fedora/CentOS/RHEL
code: bash
$ sudo yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite \
sqlite-devel openssl-devel xz xz-devel libffi-devel
macOS
code: zsh
% brew install openssl readline sqlite3 xz zlib
Linux系 (Windows以外)
pyenv をインストールするためには、次のように行います。
code: zsh
これにより、pyenv といくつかのプラグインがインストールされます。
pyenv: 実際のpyenvアプリケーション
pyenv-virtualenv: pyenvと仮想環境のためのプラグイン
pyenv-update: pyenvをアップデートするためのプラグイン
pyenv-doctor: pyenvのアップデート用プラグインです。pyenvとビルドの依存関係がインストールされているか確認するプラグイン
pyenv-which-ext: システムコマンドを自動検索するプラグイン
次の内容を シェルの設定ファイルに追加しておきます。
Bashの場合
code: 追加 ~/.bash_profile
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
Zshの場合
code: 追加 ~/.zshrc
eval "$(pyenv init -)"
code: 追加 ~/.zshprofile
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
最後に、次のコマンドでシェルを再起動するか、別のターミナルを開きます。
code: zsh
% exec $SHELL -l
Windwos
code: zsh
% pip install pyenv-win
環境変数を編集を開きユーザの環境変数に変数PYENVを作成する。
変数名にPYENV、値に以下のパスを設置する。
code: TEXT
%USERPROFILE%\.pyenv\pyenv-win
ユーザの環境変数に変数path の先頭にパスを挿入する。
code: TEXT
%PYENV%\bin
pyenvを使ってPythonをインストールする
pyenvがインストールできたら、次はPythonのインストールです。Pythonにはたくさんのバージョンがあり、その中から選ぶことができます。CPython 3.9 から 3.10 のすべての利用可能なものを見たいと思った場合は、次のようにします。
code: zsh
% pyenv install --list | egrep " 3.9| 3.10"
3.9.0
3.9-dev
3.9.1
3.9.2
3.9.4
3.9.5
3.9.6
3.9.7
3.9.8
3.9.9
3.10.0
3.10-dev
Python 3.10.0 をインストールする場合は、次のようにコマンドを実行します。
code: zsh
% pyenv install 3.10.0
pyenvを使っていると、インストールしたい新しいバージョンが表示されない場合は、pyenv update を実行して pyenv を更新し、最新バージョンにアクセスできるようにする必要があるかもしれません。
これで、~/.pyenv/versions/3.10.0 以下に Python 3.10.0 がインストールされました。
もし、不要になった場合は、pyenv uninstall を実行します。
code: zsh
% pyenv uninstall バージョン
これは、内部では、次のように該当するバージョンのディレクトリを削除しているだけです。
code: zsh
% rm -rf ~/.pyenv/versions/バージョン
新しいPythonに切り替える
さて、いくつかの異なるバージョンのPythonをインストールしたので、それらを使用するための基本的な方法を見てみましょう。まず、インストールされている(つまり、自分が持っている)Pythonのバージョンを確認します。
code: zsh
% pyenv versions
* system (set by /Users/goichiiisaka/.pyenv/version)
3.10.0
ここで表示されている * は、システムPythonのバージョンが現在アクティブであることを示しています。これは、ルートの pyenv ディレクトリにあるファイルで設定されていることにも気づくでしょう。これは、デフォルトでは、まだシステムPythonを使用していることを意味しています。
code: zsh
% python -V
Python 2.7.16
% pyenv which python
/usr/bin/python
Python 3.10.0 に切り替えてみます。
code: zsh
% pyenv global 3.10.0
code: zsh
% python -V
Python 3.10.0
% pyenv which python
/Users/goichiiisaka/.pyenv/versions/3.10.0/bin/python
異なるバージョンのPythonを簡単に切り替えることができるようになりました。
pyenv のコマンドについて
前述の which のように pyenv には沢山のコマンドがあります。
code: zsh
% pyenv commands
--version
activate
commands
completions
deactivate
doctor
exec
global
help
hooks
init
install
installer
local
offline-installer
prefix
rehash
root
shell
shims
uninstall
update
version
version-file
version-file-read
version-file-write
version-name
version-origin
versions
virtualenv
virtualenv-delete
virtualenv-init
virtualenv-prefix
virtualenvs
whence
which
各コマンドには、より詳細な情報を表示する --help フラグが付いています。例えば、which コマンドの詳細情報を見たい場合は、次のように実行します。
code: zsh
% pyenv which --help
Displays the full path to the executable that pyenv will invoke when
you run the given command.
Use --nosystem argument in case when you don't need to search command in the
system environment.
install
前述しているように、pyenv install は指定したバージョンのPythonをビルドしてインストールします。
例えば、python 3.9.9 をインストールする場合は次のようになります。
code: zsh
% pyenv install 3.9.9
versions
インストールされているPythonバージョンを表示します。
code: zsh
% pyenv versions
system
* 3.10.0 (set by /Users/goichiiisaka/.pyenv/version)
3.9.9
system はシステムにインストールされているPythonのことです。* は現在有効になっているPythonバージョンを表しています。
version は現在有効になっているPythonバージョンだけを表示します。
code: zsh
% pyenv version
3.10.0 (set by /Users/goichiiisaka/.pyenv/version)
which
whichコマンドは、システムの実行ファイルのフルパスを確認するときに便利です。pyenvはシンボリックリンクを使って動作しているので、このコマンドを使えば、pyenvが実行している実行ファイルのフルパスを確認することができます。例えば、pipがどこにインストールされているかを確認したい場合は、次のように実行します。
code: bash
% pyenv which pip
/Users/goichiiisaka/.pyenv/versions/3.10.0/bin/pip
global
globalコマンドは、Pythonのグローバルバージョンを設定します。これは他のコマンドで上書きすることができますが、特定のPythonバージョンをデフォルトで使用することを保証するのに便利です。もし、デフォルトでPython 3.9.9を使いたい場合は、次のように実行します。
code: bash
% pyenv global 3.9.9
このコマンドは、~/.pyenv/version を 3.9.9 に設定します。
code: zsh
% cat ~/.pyenv/version
3.9.9
local
localコマンドは、アプリケーション固有のPythonバージョンを設定するためによ使われます。このコマンドを使って、Pythonバージョンを3.10.0 に設定するためには、次のようにコマンドを実行します。
code: zsh
% pyenv local 3.10.0
このコマンドを実行すると、カレントディレクトリに .python-version ファイルが作成されます。 pyenv が有効であれば、このファイルは自動的に読み込まれて、このPythonバージョンが有効になります。つまり、そのディレクトリおよびサブディレクトリでだけ有効になるということです。
code: zsh
% cat .python-version
3.10.0
% python -V
Python 3.10.0
% cd Projects/Python.Osaka
% python -V
Python 3.10.0
% cd /tmp
% python -V
Python 3.9.9
shell
shell コマンドは、シェル固有の Python バージョンを設定するために使用します。例えば、Pythonの3.10.0を使う場合は、次のようにします。
code: zsh
% pyenv shell 3.10.0
このコマンドは環境変数 PYENV_VERSION を設定するものです。この環境変数が設定されている間だけ、そのバージョンのPython が実行されます。
pyenv のバージョン決定するロジック
pyenv は以下のリソースを順に読み込んで使用するPythonのバージョンを決定します。
環境変数 PYENV_VERSION(指定されている場合):現在のシェルセッションで環境変数 PYENV_VERSION を設定するには、pyenv shell コマンドを使用します。
カレントディレクトリにあるアプリケーション固有の .python-version ファイル (もしあれば): 現在のディレクトリの .python-version ファイルは、pyenv local コマンドで変更できます。ファイルシステムのルートに到達するまで、各親ディレクトリを検索して最初に見つかる.python-versionファイルをバージョンを使用します。
グローバルな $(pyenv root)/version ファイル: このファイルは pyenv global コマンドで変更することができます。グローバルバージョンファイルが存在しない場合、pyenvはあなたが システムPythonを使用したいと仮定します。つまり、pyenvが有効になっていないときにに実行されるPythonのバージョンです。
仮想環境と pyenv
仮想環境は、Pythonのインストールやアプリケーションを管理する上で大きな役割を果たします。もし仮想環境について聞いたことがなければ、「Pythonの仮想環境 venv 入門 を」参照してください。 pyenv には pyenv-virtualenv という素晴らしいプラグインがあり、複数の Python バージョンと複数の仮想環境を簡単に扱うことができます。もしあなたが pyenv や pyenv-virtualenv、そして virtualenv や venv のようなツールの違いを疑問に思っているなら、心配しないでください。あなただけではありません。
まず理解しておくべきことは次の通りです。
pyenv: 複数のバージョンのPython自体を管理します。
virtualenv / venv: 特定の Python バージョンの仮想環境を管理します。
pyenv-virtualenv: 様々なバージョンの Python の仮想環境を管理します。
既にvirtualenv や venv を使っていたとしても、 pyenv はどちらともうまく動作します。
pyenv をインストーラスクリプトを使ってインストールしているので、すでにpyenv-virtualenvが使える状態になっています。
仮想環境の作成
仮想環境の作成は1つのコマンドで行えます。
code: zsh
% pyenv virtualenv python_version environment_name
python_versionは実際は省略することができるのですが、仮想環境で使用するるPythonのバージョンを確実に把握するために、明示的に指定することをおすすめします。
environment_name は、環境を分けるための名前です。通常は、環境名をプロジェクトと同じ名前にしておきます。例えば、プロジェクト tutorials で、Python 3.10.0で開発したいときは、次のように実行します。
code: zsh
% pyenv virtualenv 3.10.0 tutorials
作成済みの仮想環境を表示するためには、次のように実行します。
code: zsh
% pyenv virtualenvs
3.10.0/envs/tutorials (created from /Users/goichiiisaka/.pyenv/versions/3.10.0)
tutorials (created from /Users/goichiiisaka/.pyenv/versions/3.10.0)
バージョンの有効化
仮想環境を有効にするためには、次のように実行します。
code: zsh
% pyenv local tutorials
(tutorials) %
pyenv local コマンドは前述したときは、Python のローカルバージョンを変更するときに使用しましたが、今回は仮想環境名を指定します。これにより、カレントディレクトリに .python-version ファイルが作成され、シェルの設定ファイルで eval $(pyenv virtualenv-init -) を実行しているので、自動的にこの仮想環境が有効になります。
code: zsh
(tutorials) % cat .python-version
tutorials
(tutorials) % python -V
Python 3.10.0
(tutorials) % cd ..
% python -V
Python 2.7.16
Python と pip のパスを確認してみましょう。
code: zsh
(tutorials) % pyenv which python
/Users/goichiiisaka/.pyenv/versions/tutorials/bin/python
(tutorials) % pyenv which pip
/Users/goichiiisaka/.pyenv/versions/tutorials/bin/pip
tutorials という新しいバージョンが作成され、そのバージョンのpythonが実行されることがわかります。
code: zsh
(tutorials) % ls ~/.pyenv/versions/tutorials/bin
Activate.ps1 activate.fish pip3.10 python3
activate pip pydoc python3.10
activate.csh pip3 python
仮想環境にインストールされているPythonパッケージを確認してみましょう。
code: zsh
(tutorials) % pip list
Package Version
---------- -------
pip 21.2.3
setuptools 57.4.0
WARNING: You are using pip version 21.2.3; however, version 21.3.1 is available.
You should consider upgrading via the '/Users/goichiiisaka/.pyenv/versions/3.10.0/envs/tutorials/bin/python3.10 -m pip install --upgrade pip' command.
(tutorials) % python3.10 -m pip install --upgrade pip
Requirement already satisfied: pip in /Users/goichiiisaka/.pyenv/versions/3.10.0/envs/tutorials/lib/python3.10/site-packages (21.2.3)
Collecting pip
Using cached pip-21.3.1-py3-none-any.whl (1.7 MB)
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 21.2.3
Uninstalling pip-21.2.3:
Successfully uninstalled pip-21.2.3
Successfully installed pip-21.3.1
(tutorials) %
pip と setuptools しかインストールされていないことが確認できます。ここでは、他に pip を更新することもしています。
もし、シェルの設定ファイルで eval "$(pyenv virtualenv-init -) を実行するように設定していなかった場合は、次の方法で、有効化/無効化することができます。
code: zsh
% pyenv activate environment_name
% pyenv deactivate
これは、.python-version ファイルが存在しているディレクトリに入ったり出たりするときに、pyenv-virtualenv が行っていることと同じです。
複数の仮想環境での作業
ここまでの説明で、複数の仮想環境で効率的に作業することができるようになります。
いま時点での Python バージョンは次のようになっています。
code: zsh
(tutorials) % pyenv versions
system
3.10.0
3.10.0/envs/tutorials
3.9.9
* tutorials (set by /Users/goichiiisaka/Projects/Python.Osaka/Tutorial.Poetry/.python-version)
もし、プロジェクト projectで Python 3.8.12 が必要になった場合は、次の手順を踏めばよいだけです。
code: zsh
(tutorials) % pyenv install 3.8.12
...
(tutorials) % pyenv virtualenv 3.8.12 project1
...
(tutorials) % pyenv virtualenv 3.10.0 project2
...
(tutorials) % cd project1
(tutorials) % pyenv local project1
(project1) % python -V
Python 3.8.12
仮想環境の pyenv local で指定したあとは、そのディレクトリに移動するだけで、自動的にPythonバージョンが切り替わります。
code: zsh
(tutorials) % cd ../project2
(tutorials) % pyenv local project2
(project2) % python -V
Python 3.10.0
(project2) % cd ../project1
(project1) % python -V
Python 3.8.12
複数のPythonバージョンの同時起動
上の例で説明したように、project1 は 3.8.12を使用しています。そのコードがPython3.10でも動作することを確認したいとします。python3.10を実行してみると、このようになります。
code: zsh
(project1) % python3.10 -V
pyenv: python3.10: command not found
The `python3.10' command exists in these Python versions:
3.10.0
3.10.0/envs/project2
3.10.0/envs/tutorials
project2
tutorials
Note: See 'pyenv help global' for tips on allowing both
python2 and python3 to be found.
この出力は、Python 3.10 が現在の有効になっている仮想環境で見つからないことと、他の仮想環境では利用できることを表示しています。
この場合、次のようにすることで project1 で Python 3.10.0 を使用することができるようになります。
code: zsh
(project1) % pyenv local project1 3.10.0
(project1) % python3.10 -V
Python 3.10.0
(project1) % python3.8 -V
Python 3.8.12
(project1) % python -V
Python 3.8.12
python3.8 と python3.10 を使い分けることができ、デフォルトは python3.8 のままです。
これは、実行するためにPATH上に複数のバージョンのPythonを必要とするtoxのようなツールにとって非常に便利です。
注意 pyenv と tox を組み合わせて使用する場合、tox-pyenv パッケージをインストールする必要があります。
元に戻す場合は、次のように実行します
code: zsh
(project1) % pyenv local project1
仮想環境を削除する
今の時点で、仮想環境は次のようになっています。
code: zsh
(tutorials) goichiiisaka@GoichiMacBook Tutorials % pyenv virtualenvs
3.10.0/envs/project2 (created from /Users/goichiiisaka/.pyenv/versions/3.10.0)
3.10.0/envs/tutorials (created from /Users/goichiiisaka/.pyenv/versions/3.10.0)
3.8.12/envs/project1 (created from /Users/goichiiisaka/.pyenv/versions/3.8.12)
project1 (created from /Users/goichiiisaka/.pyenv/versions/3.8.12)
project2 (created from /Users/goichiiisaka/.pyenv/versions/3.10.0)
* tutorials (created from /Users/goichiiisaka/.pyenv/versions/3.10.0)
このうち project2 を削除したいときは、次のようにコマンドを実行します。
code: zsh
(tutorials) % pyenv virtualenv-delete project2
pyenv-virtualenv: remove /Users/goichiiisaka/.pyenv/versions/3.10.0/envs/project2? (y/N) y
確認が求められるので y を入力すると削除されます。--forceオプション(あるいは-f)を与えると直ぐに削除されます。
code: zsh
% pyenv virtualenvs
3.10.0/envs/tutorials (created from /Users/goichiiisaka/.pyenv/versions/3.10.0)
3.8.12/envs/project1 (created from /Users/goichiiisaka/.pyenv/versions/3.8.12)
project1 (created from /Users/goichiiisaka/.pyenv/versions/3.8.12)
* tutorials (created from /Users/goichiiisaka/.pyenv/versions/3.10.0)
削除されるのはpyenv が管理している仮想環境だけで、実際のプロジェクトのディレクトリはそのまま残っています。
まとめ
pyenv を使うことで、複数の仮想環境と複数のPythonバージョンを自由に切り替えて使用することができます。開発マシンでのパッケージの依存関係に悩むこともなく、最新のPythonバージョンをより簡単にテストすることができるようになります。
所感
個人的には conda の方が pyenv よりも好ましいと考えています。理由は、
conda でシステム側のライブラリやパッケージをインストールすることができる:システム側をまったく汚さずにプロジェクトを開発することができます。言い換えると、プロジェクトに必要な要件を完全にユーザ側で管理することができます。
クラスプラットフォーム: pyenv では Windows は別のプロジェクト pyenv-win をインストールする必要があります。
conda ではNumPyやSciPyはIntel MKL(Math Kernel Library) を使ってビルドされているため圧倒的にパフォーマンスが良い。
pyenv ではソースをダウンロードしてビルドする必要がありますが、conda ではビルド済みなのでインストールが速い。
pyenv ではシステム側にビルドするための環境が必要になる。
conda に比べて pyenv の方が良いなと思えることは、次のものです。
Python 3.9.0 を使っていて、Python 3.9.9 をインストールしたようなとき、conda では追加したパッケージもすべてインストールする必要がありますが、pyenv では同じ 3.9.x なので site-packages を共有できる。
参考