pyenv

pyenv とは

pyenv は、複数のバージョンの Python をインストールし、使用する Python のバージョンを簡単に切り替えるためのツールです。 pyenv を使用すれば、同じマシン上でありながらも、あるプロジェクトではバージョン 3.x の Python を、 また別のプロジェクトではバージョン 3.y の Python を使用する、といったことを容易におこなうことができます。

pyenv の利点

たとえば、プロジェクトごとに使用する Python のバージョンが異なっていたり、 あるいは複数のバージョンの Python でテストをおこないたい場合があります。 このような要求に対して、システムにあらかじめインストールされている Python を使用することはできません。 また、aptbrew などのパッケージマネージャを使用したとしても、 任意のバージョンを選択できるわけではなく、また複数のバージョンをインストールすることも簡単ではありません。

pyenv は、こうした問題を解決します。 すなわち、バージョンが異なる Python のインストール、使用するバージョンの指定、バージョン間の容易な切り替え、などの利点をもたらしてくれるのです。

インストール

pyenv をインストールする方法は、公式ドキュメントを参照してください。

pyenv のインストールが完了したら、次のコマンドにより、pyenv が使用できることを確認しましょう:

$ pyenv --version
pyenv 1.2.20

インストール可能なバージョンを表示する

pyenv のインストールが完了したら、インストール可能な Python のバージョンを確認しましょう。 すべてのインストール可能なバージョンを列挙するには次のコマンドを実行します:

$ pyenv install --list
...

非常に多くの結果が表示されるはずです。目的のバージョンをスムーズに見つけるために、適宜 grep などを用いて結果をフィルタリングしましょう:

$ pyenv install --list | grep " 3.8"
  3.8.0
  3.8-dev
  3.8.1
  3.8.2
  3.8.3
  3.8.4rc1

Python をインストールする

目的のバージョンが見つかったら、install コマンドによりインストールしましょう:

$ pyenv install -v 3.8.3

pyenv install を実行すると、対象のバージョンの Python がソースコードからビルドされます。 -v オプションにより、ビルド時の出力が表示されます。 不要であれば省略しましょう。

マシンにインストールされた Python を確認するためには、versions コマンドを実行します:

$ pyenv versions
* system (set by /home/foo/.pyenv/version)
  3.8.3

ここでは system3.8.3 の二種類が表示されています。 * は、現在アクティブとなっているバージョンを示します。 つまり、デフォルトでは、システムにインストールされた Python を使用するように設定されています。

このことは、pyenv のコマンドである which によっても確認することができます。 which は、指定したコマンドの実体へのフルパスを表示します。 次のコマンドにより、python コマンドを実行する際に使用されるファイルを調べることができます:

$ pyenv which python
/usr/bin/python

このコマンドの結果からも、現在指定されている Python がシステムにインストールされているものであることが確認できます。

Python を使用する

使用する Python を指定するためのコマンドには、globallocalshell という 3 種類のコマンドがあります。 ここでは、global コマンドを使用する方法を見ていきます。

global コマンドは、その名の通り、デフォルトで (マシン内でグローバルに) 使用する Python を指定します。 たとえば、上でインストールしたバージョン 3.8.3 を global コマンドによりセットする方法は、次のようになります:

$ pyenv global 3.8.3
$ pyenv which python
/home/foo/.pyenv/versions/3.8.3/bin/python

which コマンドによって表示されるパスが変化していることがわかります (また、実行ファイルがホームディレクトリ下の .pyenv に生成されていることも確認できます)。 Python の REPL を実行し、実際に Python のバージョンが切り替わっていることを確認してみましょう:

$ python
Python 3.8.3 (default, Jul 11 2020, 19:35:22)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

このように、global コマンドによって使用するバージョンを簡単に切り替えることができます。

複数のバージョンを使用する

次に、local コマンドにより、プロジェクトごとに Python のバージョンを切り替える方法を示します。 local コマンドは、ディレクトリのレベルで有効な Python を設定するためのコマンドです。

たとえば、次のようにコマンドを実行することで、my-project ディレクトリ以下の Python のバージョンを 3.7.6 へと設定することができます:

$ pyenv install 3.7.6
$ pyenv versions
  system
  3.7.6
* 3.8.3 (set by /home/foo/.pyenv/version)
$ mkdir my-project
$ cd my-project
$ pyenv local 3.7.6

version コマンドを使用して、バージョンが切り替わっていることを確認しましょう:

$ pyenv version
3.7.6 (set by /home/foo/my-project/.python-version)
$ python --version
Python 3.7.6

この設定は、このディレクトリ内に固有のものとなります。つまり、このディレクトリの外に出れば、使用されるバージョンは自動的に切り替わります:

$ cd ..
$ pyenv version
3.8.3 (set by /home/foo/.pyenv/version)
$ cd my-project
$ pyenv version
3.7.6 (set by /home/foo/my-project/.python-version)

このように、プロジェクトごとに pyenv local コマンドを実行することで、使用する Python のバージョンを自動的に切り替えることが可能となります。

pyenv が使用するバージョンを切り替える仕組み

pyenv は、使用する Python のバージョンをどのような仕組みにより切り替えているのでしょうか? 先ほど local コマンドを実行したディレクトリに対して、ls -a コマンドを実行してみましょう:

$ ls -a my-project
.               ..              .python-version

.python-version というファイルが作成されています。 このファイルの中身を確認してみましょう:

$ cat my-project/.python-version
3.7.6

指定した Python のバージョンが書き込まれていることがわかります。 このファイルこそ、pyenv が使用する Python のバージョンを決定するためのヒントとなっているのです。

それでは、pyenv がバージョンを切り替える仕組みをみていきましょう。 pyenv は、次のようなステップで使用するバージョンを決定しています:

  1. pyenv shell によって環境変数 PYENV_VERSION がセットされていれば、そこで指定されているバージョンを使用する
  2. pyenv local によって生成された .python-version がカレントディレクトリまたは親ディレクトリにあれば、そこで指定されているバージョンを使用する
  3. pyenv global によって指定されているバージョンを使用する

私たちはまだ、環境変数 PYENV_VERSION をセットしていません。 よって、いずれのディレクトリにおいても、pyenv はステップ 1 をスキップします。 my-project ディレクトリ内には .python-version が存在するため、その内部であれば、pyenv はステップ 2 により .python-version で指定されたバージョンを使用します。 一方、my-project ディレクトリの外では、親ディレクトリをたどっていっても .python-version が見つからないため、pyenv はステップ 3 により global で指定されたバージョンを使用します。

以上が、これまでの例で pyenv がどのように使用するバージョンを決定していたかの説明となります。

最後に、shell コマンドについて説明します。 shell コマンドは、シェルに固有の Python のバージョンを設定するためのコマンドです。 shell コマンドを実行すると環境変数 PYENV_VERSION がセットされ、そのシェルを開いている間のみ使用するバージョンを設定することができます。

たとえば、以下のコマンドでは、使用するバージョンを system へと設定しています:

$ pyenv shell system
$ pyenv versions
* system (set by PYENV_VERSION environment variable)
  3.7.6
  3.8.3
$ printenv | grep PYENV_VERSION
PYENV_VERSION=system

ここで、local コマンドによりバージョン 3.7.6 を設定した my-project ディレクトリに移動し、どうなるかを確認しましょう:

$ cd my-project
$ pyenv version
system (set by PYENV_VERSION environment variable)
$ python --version
Python 2.7.18rc1

ここでも、使用されるバージョンは変化していません。 上記したステップ 1 を見ればわかる通り、環境変数 PYENV_VERSION が設定されていることから、pyenvlocal で設定された値よりも PYENV_VERSION で設定された値を優先して使用しているのです。

なお、shell --unset により、PYENV_VERSION の設定を解除することができます:

$ pyenv shell --unset
$ pyenv version
3.7.6 (set by /home/foo/my-project/.python-version)

以上により、pyenv が使用する Python のバージョンを決定する仕組みがわかりました。

不要なバージョンを削除する

不要になったバージョンは、uninstall コマンドにより削除することができます。 たとえば、上でインストールしたバージョン 3.7.6 を削除するには、次のようにコマンドを入力します:

$ pyenv uninstall 3.7.6
pyenv: remove /home/foo/.pyenv/versions/3.7.6? [y|N]y
pyenv: 3.7.6 uninstalled

まとめ