この記事の目的
pyenv, virtualenvがどのような仕組みでPython実行環境を作っているのか説明する。導入方法、使用方法には特に触れない。説明は参照サイトの翻訳で、それ以上の情報はない。
参照サイト
pyenv
概要
pythonのバージョンを同一端末内で使い分けるためのツール。作業ディレクトリ毎に用いるpythonのバージョンを設定できる。
仕組み
構成要素
pyenvでインストールされる各バージョンのpythonは下記のように保存される。ちなみにpyenvで指定するバージョン名はフォルダ名そのままである。
$HOME/.pyenv/shims/ # pyenvの仕組みの核。各shimコマンドが配置される。
|-/versions/2.7.8/ # インストールしたPythonインタプリタ
|-/3.4.2/ # 例として2.7.8, 3.4.2, pypy-2.4.0をインストールした場合このようになる
|-/pypy-2.4.0/
|-/version # globalで使うpythonのバージョン情報ファイル
また、python localコマンドを使うことで、任意の作業ディレクトリに.python-versionファイルが配置される。
python globalコマンドでは、$HOME/.pyenv/versionファイルが編集される。
.python-versionと$HOME/.pyenv/versionファイルには、名前の通り利用するpythonのversion情報が記述されているのみである。
そして$HOME/.pyenv/shims/以下にshimコマンドが作成される。これについては次節で説明する。
shimとバージョン切り替えの仕組み
shimコマンドとは、pythonコマンド(python, pip等)と同名で、$HOME/.pyenv/shims/に配置されるコマンド群である。一口に言うと、バージョン情報を探索したのち、該当するバージョンの同名コマンドを実行するコマンドである。具体的な手順は下記の通り。
-
環境変数
PYENV_VERSIONを調べ、もしバージョン情報があれば、それを利用する。 -
環境変数
PYENV_VERSIONに情報がない場合、.python-versionファイルが同ディレクトリにあれば、それに記載されたバージョンを利用する。 -
同ディレクトリに
.python-versionファイルがなければ、親ディレクトリを探索し、.python-versionファイルが存在しないか調べる。 -
上記の探索でバージョン情報が見つからない場合、
~/.pyenv/versionファイルに記載された情報を利用する。このファイルすらない場合、system標準にあるPythonを利用する。
このshimコマンドを利用するために、$HOME/.pyenv/shims/をシステム標準のコマンドがあるPATHより左側に$PATHを設定しなければならない。
~/.pyenv/shims:/usr/local/bin:/usr/bin:/bin
ちなみに、pyenv rehashはこのshimsコマンドを現在インストールされてるpythonバージョン群に基づいて再構成するコマンドである。
virtualenv
virtualenvで構築されるディレクトリ
virtualenvコマンドで任意のディレクトリにPython実行環境を作成できる。このディレクトリ構成は単にPythonインタプリタのディレクトリと同じ構成である。Pythonコマンドは、自身の親ディレクトリにあるinclude, libディレクトリを参照するようだ。なので、virtualenvはただそのディレクトリ構成を作成し、必要なモノを入れ込むだけである。ちなみにPythonコマンドなどは、シンボリックリンクをはるのみである。実物をコピーしたい場合は--always-copyオプションを使う。
# $VIRTUAL_ENVはvirtualenvコマンドで作成したディレクトリ
$VIRTUAL_ENV/bin/ # Python, pip等実行ファイル群
|-/include/ # C headerが配置される
|-/lib/ # 追加ライブラリが配置される
|-/pythonX.X/site-package
activate scriptで設定される環境変数
$PATHに$VIRTUAL_ENV/binを追加するだけ。python実行を、$VIRTUAL_ENV/bin/pythonとしても、仮想環境のPythonを問題なく実行できそう。
# activateスクリプトから抜粋
PATH="$VIRTUAL_ENV/bin:$PATH"
unset PYTHONHOME
まとめ
pyenvのshimの仕組みはちょっと面白い。virtualenvがやってることはそんなに複雑ではない。pyenvにインストールしたバージョンを使いたい場合、次のようにすればよさそう。
$ virtualenv path-to-desired-env --python=$HOME/.pyenv/versions/2.7.8/