pyenv の Anaconda/Miniconda 対応について

2015 年は [td-client-python](https://github.com/treasure-data/td-client-python) のリリースに始まって (正確には 2014 年の Advent Calendar の [Python Pandasからトレジャーデータを叩く](http://qiita.com/kiyoto/items/2d8d49e3a9b34f652e52)?)、Treasure Data にとっての Python 元年と呼ぶことのできる年だったと思います。

何か td-client-python について書こうかとも思ったのですが、ソース読めば分かるようなことを書き下してもあまり面白くないので、ソースを読んでもよく分からないと一部で評判の pyenv および pyenv-virtualenv の実装についてこの機会に一部説明しようと思います。ぶっちゃけ Treasure Data とあんまり関係ないけど、td-client-python のテストにも pyenv 使ってるし Advent Caledar に書いても許される... はず。

# pyenv とは

2012 年の夏頃にふと思い立って rbenv のツリーをまるっとコピーして `sed -e 's/RBENV/PYENV/g' -e 's/RUBY/PYTHON/g'` してみたのから始まった、要するに rbenv for Pythonista です。もともと、複数の CPython バージョンや PyPy なんかの間を簡単に行き来できるようにするのが作った目的だったので、CPython だけでなく PyPy、Jython、Stackless、IronPython などの各種フレーバのインストールもサポートしています。一部 rbenv から意図的に仕様を変更している部分もありますが、概ね rbenv と同様の使用感で使えるようになっているはずです。

## pyenv-virtualenv とは

数年前まで、複数の virtualenv を管理するには `virtualenvwrapper` の使用が一般的だったと思いますが、 _色々と思うところがあった_ ので複数の virtualenv を pyenv のバージョンとして管理できるようにしたものです。思い付きで作り始めた当初は `virtualenv` コマンドをラップしただけのスクリプトでしたが、その後に virtualenv の自動アクティベート機能やらも追加されて、少しづつ便利にそしてファットになってきているような気がします。

pyenv で virtualenv を管理するためのプラグインとしては [pyenv-virtualenvwrapper](https://github.com/yyuu/pyenv-virtualenvwrapper) というものもあって、こちらも結構がんばって実装はしてあるものの、シェル関数として動作する virtualenvwrapper と shims スクリプトで動く pyenv の相性の悪さがどうにもならず、よっぽど virtualenvwrapper に思い入れがある人以外にはあまりお勧めしません。

# pyenv における Anaconda/Miniconda 対応のはじまり

2 年くらい前から pyenv のバージョンとして anaconda, anaconda3, miniconda, miniconda3 なんかを選択できるようになっていました。基本的には Continuum Analytics が標準で配布している `.sh` をダウンロードしてきて叩くだけの簡単なお仕事でした。

## pyenv における Anaconda/Miniconda 対応の問題点

適当に Anaconda を pyenv にインストールできるようにはしてみたものの、実際にインストールしてみると結構もろもろ問題があることに気がつきました。たとえば、

1. `curl` や `openssl` などが Anaconda に乗っ取られる
  * Anaconda が標準で自身の prefix に `curl`, `openssl`, `sqlite3`, `redis` などもろもろインストールしてしまうため
2. そもそも `curl` が壊れてて Debian だと動かない
  * CA 証明書が `/etc/pki/tls/certs/ca-bundle.crt` にないと動かない
3. 付属の `activate` スクリプトが使えない
  * pyenv は shims スクリプトで `$PATH` を乗っ取るので、 `source activate foo` みたいなことやっても期待通りのスクリプトを `source` することはできません

ぶっちゃけ、これまで pyenv で Anaconda をインストールすることはできても上記問題により `pyenv global` に Anaconda を設定でもしない限り常用するのは厳しい状態でした。個人的にもほとんど Anaconda は使わず Miniconda3 しか使ってませんでした。

# pyenv における Anaconda/Miniconda 対応について

せっかく社内的にも Python 熱が高まりつつあるのにこのまま Anaconda 対応が微妙なまま放置するのも困りものだと思い、せっかくなんでなんとかなるように色々と直してみました。大雑把に思い付くところを挙げてみると、

1. conda env を virtualenv と同様に pyenv のバージョンとして扱えるよう変更 ([yyuu/pyenv#471](https://github.com/yyuu/pyenv/pull/471))
2. `curl`, `openssl`, `sqlite3` などについては可能な限り Anaconda/Miniconda 同梱のものでなく `system` にインストールされているものを使用するよう変更 ([yyuu/pyenv#491](https://github.com/yyuu/pyenv/pull/491))
3. `pyenv activate` で virtualenv だけでなく conda env もアクティベートできるようにした ([yyuu/pyenv-virtualenv#104](https://github.com/yyuu/pyenv-virtualenv/pull/104))
4. `activate` スクリプトを用意して `source activate foo` のような形式で conda env もアクティベートできるようにした ([yyuu/pyenv-virtualenv#108](https://github.com/yyuu/pyenv-virtualenv/pull/108))
5. `pyenv virtualenv` で virtualenv を作成する際、`virtualenv` と `pyvenv` だけではなく `conda create` でも環境を作るようにした ([yyuu/pyenv-virtualenv#125](https://github.com/yyuu/pyenv-virtualenv/pull/125))

などなど結構いろいろと手を入れることになりました…。とりあえず、上記の対応によって先に挙げた pyenv で Anaconda を使ううえでの問題点はほぼ解消したものと考えています。

# まとめ

CPython の上に `matplotlib` などを _きちんと_ インストールして Jupyter をセットアップしたりするのは結構しんどい (特に OS X で `--enable-framework` とか要求されるとつらい) ので、Anaconda/Miniconda を pyenv から普通に扱えるようになったことは一つの前進だと考えます。今後も Pandas や Jupyter など、データ解析用途での使用に耐えるだけの機能を必要ならば追加してゆきたいと思います。

なお、2015/12/18 (Fri) の現時点においては、pyenv-virtualenv 側の変更は未だ Homebrew などにはリリースできていないので、変更の適用されたバージョンを使うためには https://github.com/yyuu/pyenv-virtualenv から最新の変更を取ってくる必要があります。年内には Homebrew などにもリリースしたいと思っています。


# 最後に

あと少しで fluentd の Star 数を抜けそうな気がするので、Treasure Data の社員としてはどうかと思わないでもないですが、折角ですので皆さん Star の協力をお願いします!

![fluent/fluentd](https://i.gyazo.com/2e63bc79bc3c22c1067f8bdc47e497a0.png)

![yyuu/pyenv](https://i.gyazo.com/dd62e0c565857dbad032ddc1eeb6de76.png)