pythonの環境構築戦争にイラストで終止符をどうやら打てない


# はじめに

Pythonの環境構築は僕にとって、戦争でした。

如何せんツールが多すぎます。 
インターネットで調べるとざっと挙げるだけで

- 元から入っているpython3
- 元から入っているpython3 + venv
- pyenv
- pyenv + pyenv-virtualenv
- pyenv + venv
- anaconda
- docker + python
- docker + anaconda
- ...

以上のような組み合わせが山程出てきます。

よく最近のゲームのキャラメイキングの
「組み合わせは無限大！」を思い出します。

この記事では、**それぞれの環境構築の概念**をイラスト画像でまとめようと思います。
環境構築のコマンド自体は取り扱わないためご注意下さい。

# 追記　2019/11/07

本記事はPython初心者による「概念のみ」に関する説明のため、ベストな環境構築や、すべて正確かつ詳細な内容は含んでないです。（申し訳ありません！）
どうやら僕なんかでは終止符は打てません、Pythonに強い人お願いします。

また、Pipenv, Poetryの内容は、触ったことが現在ないため、現時点では含んでおりません。

# 追記　2019/12/20

[2020 年の Python パッケージ管理ベストプラクティス](https://qiita.com/sk217/items/43c994640f4843a18dbe)

sk217さんによって，ナウいパッケージ管理がものすごくわかりやすく書かれています．
この記事よりも新しくわかりやすいため，上記の記事のほうを参考にしてください．


# 元からPCに入っているPython3

![python3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211482/fdeb24ab-ea02-b2a9-d4ae-e92f43021ac6.png)

これが一番簡単な初期状態です。
ゲームでいう、レベル$1$でRTAなどで一切キャラメイキングしてない状態です。

OSごとにもよりますが、最近のOSには初期状態でPython2やPython3がインストールされています。
当然一つのバージョンしか入っていません。
ここではPython3.7.3を想定して扱っていきます。

Pythonの一つのバージョンには、公式モジュールフォルダと、pipでインストールしたモジュールフォルダがあります。
公式モジュールには

- math
- logging
- venv
- collections

などPython公式が作ったモジュールが入っています。

一方、`pipというPythonのパッケージマネージャ`でインストールしたモジュールには

- Keras
- requests

などサードパーティが作成したモジュール(ライブラリ)などがフォルダで管理されています。

ここで、まず問題になるのが**pipでインストールするモジュールのバージョン**を切り分けられないということです。
ディレクトリAでは、Keras1.2を使いたいです。しかし、ディレクトリBでは、Keras1.0を使いたいです。
このとき、pipでは同じサードパーティ製のモジュールのバージョンは$1$つしか扱えません。

よって、ディレクトリAで作業する時はKeras1.2を再インストール、そしてディレクトリBで作業する時はKeras1.0を再インストールなど、毎回pipで入れ直す必要があります。
これだと面倒です。
さらに、機械学習では多くのライブラリが依存関係を持っており、そのたびにすべてのサードパーティモジュールをインストールし直す必要があります。

そこで、**venv**を使用することで、同じバージョンのPython下で複数の環境を作ることが可能となります。

# 元からPCに入っているPython3 + venv

![venv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211482/2aae5a01-547f-dbf6-346f-a9b3902a08dd.png)


venvは、一つのPythonのバージョン下で、複数のサードパーティ製のpip環境を切り分けることの出来る、**公式**モジュールです。
つまり、Python3.7.3の下で、プロジェクトのディレクトリごとに複数のpipサードパーティ環境を作ることができます。

上記の画像を見てみます。
元からインストールされていたPython3.7.3の公式モジュールにvenvというモジュールがあります。mathやloggingと同じ扱いのモジュールです。

venvを使うと、ディレクトリごとにpipのサードパーティライブラリ環境を作ることができます。
よって、上記の画像の通り

- DesktopのproAというプロジェクトディレクトリでは、Keras1.2をインストールして使う
- DownloadのBというプロジェクトディレクトリでは、Keras1.5をインストールして使う

のように、複数のサードパーティライブラリのバージョンを切り分けて使うことができます。


ここで、venvの大事なメリットが**Pythonバージョンx.x.xの公式venvを使うことで、そのx.x.x内部に複数のサードパーティライブラリ環境を作ることができる!**ということです。
これによって、バージョンが切り分けられてうま味になります。


しかし、このままではまだ問題があります。
例えば、以下のような状況です。

> あなたはPython3.7.3を使っており、Kerasの本を買ってきてディープラーニングの勉強をすることにしました。
しかし、その本ではPython3.6.1の環境を利用していたようです。
ここであなたは気付きました。Python3.7.3内で複数のサードパーティライブラリの環境をつくれても、**Pythonのバージョン自体は変えることができないのです。**

そこで、pyenvの出番です。

# pyenv

![pyenv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211482/afefa604-7f96-7f5e-9953-74f4ab7e50f5.png)

pyenvは、PCのOSに複数のPythonのバージョンをインストールできるミドルウェアです。

上記の画像を見てみます。
あなたはpyenvをインストールし、pyenvでpython3.7.3をインストールし通常利用しています。
そして、Kerasの本でPython3.6.1を利用していたため、pyenvでバージョン3.6.1を追加インストールしました。

pyenvで3.6.1に使用バージョンを切り替えることでKeras本と同じ環境にすることができます。
さらに、いつでも別バージョンに戻せる、というpyenvのうま味があるため、Keras本が終わったら3.7.3に戻すことができます。

これは嬉しいですね。
Pythonのバージョン自体を切り替えられるようになりました。

しかし、ここでまた新たな問題が発生します。

> あなたはせっかくPython3.6.1に切り替えましたが、Keras本で、Keras1.0を使っている環境とKeras1.2を使っている環境が混ざっていたのです。
ちゃんと一緒に統一しろや！と思いましたが、あなたはpyenvのみではバージョンは切り替えられてもサードパーティ製のライブラリのバージョンを切り替える環境が作れないことに気付きました。

そこで、pyenv + pyenv-virtualenv
または　pyenv + venv
の出番になります。

# pyenv + pyenv-virtualenv


![pyenv+virtualenv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211482/acdbc5cc-120b-b07f-dbf4-401b9ec796a0.png)

pyenvでPythonのバージョン自体を切り替えられることを説明しました。
そこで、後はそのバージョンx.x.x内で、複数のサードパーティ製のライブラリを使える環境を切り分けられればよいわけです。

そこで、pyenv-virtualenvというpyenvのプラグインミドルウェアを使うことができます。

pyenv-virtualenvを使うことで、pyenvでインストールしたPythonx.x.x内で複数のサードパーティ環境を作ることができます。
これによって、ディレクトリやプロジェクトごとに利用するライブラリバージョンを変更できます。
また、元々のPythonx.x.xのpipは汚れないため、うま味倍増です。

# pyenv + venv

![pyenv+venv (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211482/8eb6ef47-7caa-1297-e793-dddc674de2b4.png)



pyenv + venvも同様です。

pyenvで選んだPythonのバージョンx.x.x内の公式モジュールvenvを使うことで、複数のサードパーティ環境を作ることができます。

これでついに

- 好きなPythonのバージョンx.x.xを使える・切り替えられる
- そのバージョンx.x.xのライブラリ環境を切り分けられる

ことができるようになりました。

しかし、まだ一応問題は存在します。
それは、**PCの環境が汚れる**ということです。

PythonはOSのミドルウェアとして内部でも利用されています。
そのため、できればOSのPythonは汚さない・いじらないのがベストです。

そこで、**Docker**を使うことができます。

# Docker + Python

![docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211482/2292787a-8e08-b568-a27d-df34069a9c3e.png)

Dockerは、コンテナという小さなLinuxシステムをOS上のプロセスとして動かすことで、自分のPCのOSを汚すことなくアプリやライブラリを利用できるようにしてくれるミドルウェアです。

Pythonコンテナは以下のような感じになっています。

- alpineLinuxイメージに、Pythonx.x.xのバージョンがインストールされている

よって、alpineOSの上でPythonx.x.xが動いているため、自分のPCのOS（例えばMac）は汚れることが有りません。

PythonのDockerイメージは

- バージョンx.x.x
- Anaconda

など多くのイメージが用意されているため、簡単に環境を作り利用できます。
また、Kerasなどの機械学習ライブラリがすでにインストールされたイメージもあるため、うま味です。

自分のPCの環境を汚したくないときはDockerを利用すると便利です。


# 最後に

Pythonを取り巻く環境環境の概念について見てきました。
Pythonを利用している期間は僕は短く、まだまだ理解が足りていません。
間違っている点やアドバイスをいただければ嬉しいです！
ありがとうございました！


# P.S. Anaconda環境

Anacondaについて、非常に疎いため、「自分が考えているAnaconda環境」を載せます。

![anaconda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211482/e65cc426-10b2-62e2-e08b-a7d0dbe3faa3.png)

上記のような感じかと思っていますが、pip conda　ライブラリなどの仕組みがよくわかっていないため詳しい方にぜひ教えてほしいです！

Jupyter Notebookの仕組みもさっぱりです･･･（Anaconda上で動くサーバー？）