pyenv と pyenv-virtualenv で環境構築

##自分の環境を構築する方法のメモ
リモートで作業する時に必要になったのでメモる
参考にしたサイトの方がわかりやすい可能性あり
環境は、`mac OSX: Yosemite` です。


#pyenv
pyenvはpython環境を管理するものです。
標準とは違う環境のpython環境を作成できます。

参考URL：
[pyenvおよびvirtualenvの使い方](https://www.qoosky.net/references/263/)
[pyenvでPython環境を管理する方法](https://omoshetech.com/how-to-manage-python-environments-by-pyenv/)
[pyenvとvirtualenvを使ってみる](http://cocodrips.hateblo.jp/entry/2014/09/02/171127)


## 説明とか読みたくない人（知識のある人)
https://github.com/KodairaTomonori/Qiita/blob/master/shell/construct_pyenv.sh
これをコピーして、実行するとホームに環境が構築される
ホーム以外に構築したい場合は、~/の部分を任意のpathに書き換えたらできます。
※~/.bash_profileに追加書き込みされます。


##pyenvを使えるようにする
まず、git cloneする
```$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv```

そして、下記のものを`~/.bash_profile`に書き込む。（.bashrc, .bash_profileについて：[本当に正しい .bashrc と .bash_profile の使ひ分け](http://qiita.com/magicant/items/d3bb7ea1192e63fba850)

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

\* 2020/03/17 修正：ダブルクウォート追加

##それぞれのバージョンのpythonのインストール
`pyenv install 3.5.0`でインストールできます。バージョンは任意となります。
#
```install-version.
$ pyenv install 3.5.0
$ pyenv install 2.7.9
```
間違えた時のアンインストール方法は、`install`を`uninstall`に変えて実行。

##pythonのバージョンの切り替え
`pyenv global x.x.x`または、`pyenv local x.x.x`でバージョンの切り替えができます。
`global`とすると全体に、`local`にするとそのカレントディレクトリに反映されます。この反映はterminalを終了しても続くので、`local`でフォルダごとに設定するととても便利です。

そのシェルでの変更は、`shell`とすると、変更できます。これを使用した場合、今使用してるシェルでしかその環境が反映されません。なので、シェルを閉じた時後に再度開いた場合やシェルを複数開いた場合は、その環境変更は他に影響されることはありません。

一時的に使う場合は`shell`、フォルダごとに設定したい場合は`local`、全体のデフォルトの環境を変えたい場合は`global`といったところでしょうか。

`x.x.x`の部分を`system`とすることで元に戻せます。
#
```swich-python-version.
python --version
Python 2.7.3

$ pyenv shell 2.7.9
$ python --version
Python 2.7.9

$ pyenv shell 3.5.0
$ python --version
Python 3.5.0

$ pyenv shell system
$ python --version
Python 2.7.3
```

##moduleのインストール
インストールしたpython(2.7.9と3.5.0)には、デフォルトのモジュールしか入ってない(pip freezeしても何も入ってない)のでインストールします。
モジュールを入れるのは、通常通り`pip install`で任意のモジュールを入れるだけです。

```pip install xxxxx```

#pyenv-virtualenv
`pyenv`だけでも、十分便利だけど、もっと便利に。
`pyenv-virtualenv`は pyenv のプラグインで、同じ(python)バージョンで違う環境を作成するためのものです。

##インストール方法
```$  git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv```

そして、設定を`.bash_profile`に書き込む
>eval "$(pyenv virtualenv-init -)"

##新しい環境の作成
新しいpython環境の作成は、```pyenv virtualenv [version] <virtualenv-name>```とすることで新しく`virtualenv-name`という環境ができる。ここの`[version]`には、既存の環境を指定する。
##
```make_new.
pyenv virtualenv 3.5.0 new_3.5.0
```

ここで、新しく作った環境では、pyenvで作った環境の中で`pip`等でインストールしたモジュールは使えなくなっている。
`[version]`で使ってたものを使いたければ、`--system-site-package`というオプションをつける。
そうすると、`pyenv`で構築したものの`site-packages`にパスを通します。

下記の例でいうと、`--system-site-packages`をつけると、`~/.pyenv/versions/3.5.0/lib/python3.5/site-packages`がパスに加わるということです。

###
```sample_site-packages.
$ pyenv virtualenv 3.5.0 inde-3.5.0
$ pyenv virtualenv --system-site-packages 3.5.0 co-3.5.0
$ pyenv virtualenv --system-site-packages inde-3.5.0 co-inde-3.5.0

# sys.path一部省略しています。
$ python -c 'import sys; print(sys.path)'    # ここは、3.5.0
['', '~/.pyenv/versions/3.5.0/lib/python35.zip',..., '~/.pyenv/versions/3.5.0/lib/python3.5/site-packages']

(inde-3.5.0) $ python -c 'import sys; print(sys.path)'
['', '~/.pyenv/versions/3.5.0/lib/python35.zip', .... , '~/.pyenv/versions/inde-3.5.0/lib/python3.5/site-packages']

(co-3.5.0) $ python -c 'import sys; print(sys.path)'
['', '~/.pyenv/versions/3.5.0/lib/python35.zip', ... , '~/.pyenv/versions/co-3.5.0/lib/python3.5/site-packages', '~/.pyenv/versions/3.5.0/lib/python3.5/site-packages']

(co-inde-3.5.0)kodaira@fomalhaut:~$ python -c 'import sys; print(sys.path)'
['', '~/.pyenv/versions/co-inde-3.5.0/lib/python35.zip',  ... , '~/.pyenv/versions/co-inde-3.5.0/lib/python3.5/site-packages', '~/.pyenv/versions/3.5.0/lib/python3.5/site-packages']

```

他の環境のmoduleをインストールしたい時は、`pip freeze`をどっかに書き込んで、`pip install -r`でインストールできます。（`pyenv virtualenv` する時にコピーする方法ありそうだったけど見つからなかったので誰か。。。）
##
```pip_install.
---コピーしたい環境で----
$ pip freeze > pyp_list.txt
---環境変更後----
$ pip install -r pyp_list.txt
```

##仮想環境の保存と再構築
ここが一番 pyenv-virtualenv を使う利点だと思います。
環境を保存して、他の場所で同じ環境を再現する話です。

####まず、必要なもの(wheel)をインストール
#
```install_wheel.
$ pyenv exec pip install wheel
```
####wheelを使ってpipでインストールしたモジュールの情報を保存
`--wheel-dir=[dir]`で任意のディレクトリに保存
上で、`pip freeze`の出力をそのまま使いましたが、`wheel`を使った方がいいらしいです。
#
```save_module_info.
$ pyenv exec pip freeze > pyp_list.txt
$ pyenv exec pip wheel --wheel-dir=~/tmp/wheelhouse -r pyp_list.txt
```
####新しい、環境を作ったところでさっき作ったwheel使って同じものをインストール
`wheel`することで、ビルド済みのパッケージを保存できるので、毎回コンパイルせずに済む。
参考URL：[そこはかとなく書くよん。](http://tdoc.info/blog/2014/01/15/pip.html)
#
```install_using_wheel.
$ pyenv virtualenv 3.5.0 tes-3.5
$ pyenv global tes-3.5
$ pip install -r pyp_list.txt --use-wheel --no-index --find-links=tmp/wheelhouse
$ pip freeze
```

#まとめ
`pyenv`と`pyenv-virtualenv`を使うことによって環境を構築できる。
'wheel'で環境を保存でき、他の場所で同じ環境を再現できる。

間違ってるあるとか、もっと便利なのあるとかあったら教えてください