pyenv + virtualenv を使ってみる

Pythonでちょっとした処理を書いてみようと思い、 CentOSに標準で入っているPythonを調べたところ、バージョンは「2.7.5」でした。 (CentOSのバージョンは7.2.1511)

せっかくなので3系を使ってみたいなと、 バージョンアップの方法を調べていたら、「pyenv」「pyenv-virtualenv」というものがあるとのこと。 rubyで言うところの、pyenvはrbenv(つまりpythonのバージョン管理してくれるもの)で、 pyenv-virtualenvはpythonenvのpluginで、 bundlerっぽいもの(つまりpythonライブラリのバージョン管理してくれるもの)みたいです。 これらを利用し、Python環境を構築してみます。

pyenvをインストールするため、 GitHubにあるpyenvのリポジトリを持ってきます。複製先はhome配下。

$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv

.bash_profileに環境変数を書いてあげます。

export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"

設定したら、ログインし直してちゃんと設定されることを確認。

で、pyenv経由でpythonをインストールします。とりあえず最新を。

$ pyenv install 3.5.2
Downloading Python-3.5.2.tar.xz...
-> https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tar.xz
Installing Python-3.5.2...

BUILD FAILED (CentOS Linux 7 using python-build 1.0.2-9-g80e769e)

Inspect or clean up the working tree at /tmp/python-build.20160928215352.9815
Results logged to /tmp/python-build.20160928215352.9815.log

Last 10 log lines:
checking for --with-universal-archs... no
checking MACHDEP... linux
checking for --without-gcc... no
checking for --with-icc... no
checking for gcc... no
checking for cc... no
checking for cl.exe... no
configure: error: in `/tmp/python-build.20160928215352.9815/Python-3.5.2':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

はい。BUILD FAILEDです。 「no acceptable C compiler」とか言ってるのでgccを入れて、もう1回。

$ pyenv install 3.5.2
Downloading Python-3.5.2.tar.xz...
-> https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tar.xz
Installing Python-3.5.2...
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?
 
Please consult to the Wiki page to fix the problem.
https://github.com/yyuu/pyenv/wiki/Common-build-problems
 
 
BUILD FAILED (CentOS Linux 7 using python-build 1.0.2-9-g80e769e)
 
Inspect or clean up the working tree at /tmp/python-build.20160928221252.10307
Results logged to /tmp/python-build.20160928221252.10307.log
 
Last 10 log lines:
(cd /home/pyuser/.pyenv/versions/3.5.2/share/man/man1; ln -s python3.5.1 python3.1)
if test "xupgrade" != "xno"  ; then \
        case upgrade in \
                upgrade) ensurepip="--upgrade" ;; \
                install|*) ensurepip="" ;; \
        esac; \
         ./python -E -m ensurepip \
                $ensurepip --root=/ ; \
fi
Ignoring ensurepip failure: pip 8.1.1 requires SSL/TLS

はい。またBUILD FAILEDです。 「Please consult to the Wiki page to fix the problem.」とあるので、 GitHubwiki見に行ったらRequirementsが書いてありました。。。

Common build problems · yyuu/pyenv Wiki · GitHub

wikiの通り入れてあげて、

# yum install zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel xz

成功しました。

$ pyenv install 3.5.2
Downloading Python-3.5.2.tar.xz...
-> https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tar.xz
Installing Python-3.5.2...
Installed Python-3.5.2 to /home/pyuser/.pyenv/versions/3.5.2

新しいバージョン入れたんだから、rehashしとけよと。

$ pyenv rehash

せっかくなので、2系の最新も入れます。

$ pyenv install 2.7.12
$ pyenv rehash

一覧を表示。

$ pyenv versions
* system (set by /home/test/.pyenv/version)
  2.7.12
  3.5.2

バージョン切り替えは、rbenvと同じ「global」「local」「shell」で指定できます。

$ python --version
Python 2.7.5
$ pyenv shell 3.5.2
$ python --version
Python 3.5.2

systemを指定すると、OS標準のものに戻ります。

$ pyenv shell system
$ python --version
Python 2.7.5

設定をクリアするときは「--unset」をつけてあげます。

$ pyenv shell --unset

shell -> local -> global の順で有効化されていました。 基本的にrbenvと同じかな。

次にpyenv-virtualenvを入れます。pyenvと同様に、git cloneしてあげます。

# git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv

.bash_profileに追記します。

eval "$(pyenv virtualenv-init -)"

ログインし直して、init処理しておきます。

pyenv-virtualenvで新しいPython環境を作成します。 3.5.2のバージョンを複製元とし、3.5.2_virtualenvという仮想環境を作成します。

$ pyenv virtualenv 3.5.2 3.5.2_virtualenv
Ignoring indexes: https://pypi.python.org/simple
Requirement already satisfied (use --upgrade to upgrade): setuptools in /home/pyuser/.pyenv/versions/3.5.2/envs/3.5.2_virtualenv/lib/python3.5/site-packages
Requirement already satisfied (use --upgrade to upgrade): pip in /home/pyuser/.pyenv/versions/3.5.2/envs/3.5.2_virtualenv/lib/python3.5/site-packages

「Requirement already satisfied ... 」と出てきますが、FYIらしいです。 GitHubのissuesのやりとりより。

Requirement already satisfied (use --upgrade to upgrade): setuptools · Issue #457 · yyuu/pyenv · GitHub

てか、作者日本人だった。

ちなみに、仮想環境作成するときに最新のpip等を利用したい場合、 事前に複製元のPython環境で「pyenv exec pip install -U virtualenv」とvirtualenvを最新化しておけばOKとのこと。 まあ、仮想環境作成してから、個別に最新化しても問題ないです。

$ pyenv exec pip install --upgrade pip

環境が作成されたことを確認してみます。

versionsコマンドを実行してみたところ、なぜか数が多い。環境が1個多いよ。。。

$ pyenv versions
* system (set by /home/test/.pyenv/version)
  2.7.12
  3.5.2
  3.5.2/envs/3.5.2_virtualenv
  3.5.2_virtualenv

これは(恐らく)versionsコマンドの仕様で、 シンボリックリンクPythonも表示してしまっているため。 実際、--skip-aliasesオプションをつけて実行すると表示されなくなります。

$ pyenv versions --skip-aliases
* system (set by /home/test/.pyenv/version)
  2.7.12
  3.5.2
  3.5.2/envs/3.5.2_virtualenv
 
$ ll $PYENV_ROOT/versions/
合計 8
drwxr-xr-x 6 pyuser pyuser 4096  9月 29 11:32 2016 2.7.12
drwxr-xr-x 7 pyuser pyuser 4096  9月 29 11:36 2016 3.5.2
lrwxrwxrwx 1 pyuser pyuser   54  9月 29 11:36 2016 3.5.2_virtualenv -> /home/pyuser/.pyenv/versions/3.5.2/envs/3.5.2_virtualenv

(でもネット上の参考サイトでは、こんな表記ではなかったのに。。。)

仮想環境も通常のPython環境と同じように利用できます。

$ pyenv shell 3.5.2_virtualenv
$ pyenv version
3.5.2_virtualenv (set by PYENV_VERSION environment variable)

そして、ライブラリを環境ごとに個別管理できます。

$ pyenv exec pip freeze
$
$ pyenv exec pip install awscli
$ pyenv exec pip freeze
awscli==1.10.67
botocore==1.4.57
colorama==0.3.7
docutils==0.12
jmespath==0.9.0
pyasn1==0.1.9
python-dateutil==2.5.3
rsa==3.4.2
s3transfer==0.1.4
six==1.10.0

作った環境を削除したいときはuninstallコマンドを利用。

$ pyenv uninstall 3.5.2_virtualenv

作ってあげた仮想環境の設定を他環境に移行できます。 移行にはwheelが必要なので、インストールされていない場合インストールしておきます。

$ pyenv exec pip install wheel

移行元の環境にて、freezeコマンドでrequirementsファイルを作成し、wheelファイル(ビルド済みパッケージ)を出力します。

$ pyenv exec pip freeze > ~/pyp_list.txt
$ pyenv exec pip wheel --wheel-dir=~/wheelhouse -r ~/pyp_list.txt

新しい環境を作成して、先ほど出力したwheelファイルをインストールします。

$ pyenv virtualenv 3.5.2 3.5.2_virtualenv2
$ pyenv shell 3.5.2_virtualenv2
$ pyenv exec pip install -r ~/pyp_list.txt --use-wheel --no-index --find-links=~/wheelhouse