Edited at

pyenv、pyenv-virtualenv、venv、Anaconda、Pipenv。私はPipenvを使う。


はじめに


If a thing can be done adequately by means of one, it is superfluous to do it by means of several; for we observe that nature does not employ two instruments if one suffices.

-- Thomas Aquinas (1225-1274)


pyenv-virtualenv というツールを、私は長らく使ってきた。

pyenv-virtualenvは素晴らしいツールで、私はプロジェクトを切り替えるとき、Pythonの環境について一切悩むことなくただcdするだけでよかったし、他の環境で作業するときも、requirements.txtを通じて全く問題なく環境をコピーすることができていた。

私の.zshrcには、「Pyenv-virtualenvがなければ勝手にgit cloneしてパスを通し、pyenv-initを実行する」という処理が堂々と鎮座していた。

しかし、時代は変わった。

Pipenvを試したとき、私の中でpyenv-virtualenvは終わりを迎えた。

Pyenvは私にとってブルドーザーだったし、pyenv-virtualenvは私にとって時間喰い虫だったのだ。

今日はまだpyenv-virtualenvに囚われている亡霊のあなたに向けて、Pipenvへの転生の門を開こうと思う。


Pythonを取り巻く、環境戦国時代

この記事を読むために、まずはPythonにおける環境構築手法をいくつか知っておかねばならないだろう。

Pythonインタプリタには、様々なバージョンがある。もしあなたが考古学者なら、Python2系の存在を知っていることだろう。3系の中でも互換性のない変更はたくさん行われているし、あるいはPyPyIronPythonといった(よく知られた)Pythonとは異なる実装のインタプリタもある。

つまり、我々はたくさんのPythonを持っていて、それらをプロジェクトに応じて適切に切り替えなければならない。

また、Pythonには様々なパッケージがある。開発者はこれらを好き勝手にインストールして使うわけだが、もちろんこれらのパッケージにもバージョンや互換性の問題は存在する。「このプロジェクトは、このパッケージをインストールしないと動きません。ただし、バージョンxx以上yy以下です。」という注意書きがすべてのプロジェクトに存在しており、それらをうまく扱うためにはパッケージのバージョンを切り替えてくれるツールが当然必要だ。

そういうわけで、我々は2つのものごとについて仮想環境を必要としている。

すなわち、Pythonインタプリタ本体と、パッケージ群である。


まとめ

インタプリタ切替
パッケージ切替
パッケージインストール

pyenv

virtualenv

pip

venv

pyenv-virtualenv

virtualenvwrapper

Anaconda


Pipenv



pyenv

https://github.com/pyenv/pyenv

pyenvは、前述した2つのうち前者のみを担当する仮想環境マネージャである。

pyenvのやることは以下の通りである:



  • $PATHの先頭にPYENV/shimsを挿入し、あらゆるPython系コマンドへのアクセスに割り込む。

  • いま動かすべきPythonインタプリタを探す。

  • 受け取ったコマンド(例えばpython main.pypip3 install -r)を、その探したインタプリタに投げる。

すなわち、諸々のコマンドを適切な窓口に振り分ける、受付係を引き受けてくれるのである。

適切なインタプリタを探すために、pyenvは以下の操作を行う:


  • もし環境変数PYTHON_VERSIONが設定されていれば、そのバージョンに従う。

  • そうでなければ、今のディレクトリから順に親ディレクトリを遡っていく。その途中で.python_versionファイルが見つかれば、そこに書かれているバージョンに従う。

  • ルートまで遡っても見つからなければ、グローバルに設定されているバージョンに従う。

こうすることで、今いるプロジェクトにとって最も適切なPythonを起動することができるのである。

結局、Pyenvを用いる利点は以下の通り:


  • 状況に応じて適切なPythonインタプリタを、手動で切り替えることなく用いられる。

  • いろいろなPythonインタプリタを、コマンド一発でインストール・アンインストールできる。


virtualenv

https://github.com/pypa/virtualenv

virtualenvは、前述した2つの両方、すなわちPythonインタプリタとパッケージ群を同時に切り替えられる仮想環境マネージャである。

virtualenvは、ENV/以下にPythonインタプリタ、インストールされたパッケージなどすべてを保存している。そして、source ENV/bin/activateを行うと(これがvirtualenvを使うための魔法の呪文である)、その仮想環境のフォルダにパスが通る。これ以上のことは何もしない。

いちいち仮想環境の場所を探してactivateしなければならないという面倒臭さはあるものの、動作は単純明快であり、環境が分離されていることもわかりやすい。ただし、pyenvとは異なり、新しいPythonをインストールしたりはできないので注意が必要である。あくまでも$PATHを探してPythonを見つけ、そのインタプリタをコピーするだけである。

結局、virtualenvを用いる利点は以下の通りである:



  • Pythonインタプリタとパッケージの組み合わせを好きなだけ作り、分離することができる。

  • それらをactivateで切り替えることができる。


pip

https://pip.pypa.io/en/stable/

pipは、Python公式のパッケージ管理ツールである。

Pythonを知っている人であれば、この並びにpipが居るのはおかしいと思うかもしれない。

実際、pipPythonインタプリタを切り替えてはくれないし、パッケージの仮想環境を作ってくれるわけでもない。

pipがすることは、Pythonのパッケージを探し、適切なバージョンのパッケージを、依存関係を解決しながらインストールすることである。

venvpyenv-virtualenvなど、多くの仮想環境ツールはpipを使ってパッケージをインストールすることを想定している。

pipでインストールしたパッケージは、requirements.txtという形で共有することができる。

このrequirements.txtには、必要に駆られてインストールしたパッケージのほか、依存関係の解決に必要だったパッケージ、開発時に必要だったlinterパッケージなどもすべて記述されている。

別の環境でそのプロジェクトを実行したければ、適当な仮想環境の下でpip install -r requirements.txtとすれば、それらのパッケージが全てインストールされ、元と同じ環境で実行できるというわけだ。

ここでpipを紹介した理由は、もちろん、このあとpipの仕事を代替するツールが登場するからである。


pyenv-virtualenv

https://github.com/pyenv/pyenv-virtualenv

pyenv-virtualenvは、pyenvのシステムに乗っかりつつ、virtualenvを用いることができるツールである。

pyenvともvirtualenvとも別物である点に注意されたい。

pyenv-virtualenvでは、pyenvと同様のインターフェースでvirtualenvを用いることができる。しかも、pyenvのように、状況に応じて適切な仮想環境を、手動で切り替えることなく用いることができる。

すなわち、virtualenvでは

~$ cd project1  # Projectに移動

~/project1$ python -V
python 2.7.10 # まだ切り替わっていない
~/project1$ source ~/.virtualenv/project1/bin/activate # 仮想環境をアクティベート
~/project1 (project1)$ python -V
python 3.7.3 # 切り替わった

というような処理を踏んでいたのが、

~$ cd project1  # Projectに移動

~/project1 (project1)$ python -V
python 3.7.3 # もう切り替わった
~/project1 (project1)$ ls -a
. .. .python_version # .python_version に仮想環境の名前が書かれている

と、cdするだけで仮想環境の切り替えが済んでいるのである。

でも、どうやって?

実は、pyenv-virtualenvは、あらゆるコマンドのあとにactivateのチェックを行っている。

先述した、「今のディレクトリから順に親ディレクトリを遡っていく。その途中で.python_versionファイルが見つかれば、そこに書かれているバージョンに従う。」を、すべてのコマンドのあとに行っているのである。

当然、あらゆるコマンドの実行速度は目に見えて低下する。

activationの手間を省くために、かなりのコストを支払っているのである。

結局、pyenv-virtualenvを用いる利点は以下の通りである:



  • pyenvと同じインターフェースで、virtualenvを用いることができる。


  • virtualenvで用いるPythonに、pyenvでインストールしたpythonを用いることができる。


  • virtualenvactivateによるバージョンの切り替えを、手動で切り替えることなく用いられる。


venv (旧称: pyvenv)

https://docs.python.org/ja/3/library/venv.html

venvは、Python公式が提供する仮想環境マネージャである。

その挙動はvirtualenvとあまり変わらない。

公式が提供しているのだし、virtualenvを生で使うくらいならこっちを使うのがいいのではないだろうか。


virtualenvwrapper

https://bitbucket.org/virtualenvwrapper/virtualenvwrapper

virtualenvwrapperは、何かと使い勝手の悪いvirtualenvの動作を隠蔽し、変なことをしないようにするラッパーである。

使ったことがないのであんまりわからないが、おとなしくvenvを使っておけばいいと思う。


Anaconda (, miniconda, conda)

https://www.anaconda.com/

Anacondaは、Pythonインタプリタのインストールから仮想環境の作成、パッケージのインストール、その他の環境構築などなど、Pythonに纏わるあらゆることをすべて一手に引き受けるスーパーブルドーザーである。

あらゆることを引き受けるので、ここで述べているようなインタプリタのインストールや切り替え、パッケージの切り替えなども当然引き受けてくれる。

もちろん、Anacondaには、pipを代替する機能もある。例えばpipではpip install mypyとするところ、condaではconda install mypyなどとすることでmypyパッケージをインストールすることができる。

また、このパッケージ管理システムとPythonインタプリタだけを備えた最小限のAnacondaが、minicondaとして配布されている。

Anacondaを使うなら、Pythonに関するあらゆることはすべてAnacondaに任せてしまうという気持ちが必要だ。

Anacondaの担当範囲があまりにも大きすぎて、他のどんな仮想環境ツールとも競合してしまうからである。

特に、Anacondaのパッケージ管理がpipと異なることで、「ほしいパッケージのバージョンがcondaにない! でもいまさらpipは使えない……」ということが結構あったりするのだ。その点は注意しなければならない。

何にせよ、どこまでがAnacondaの支配領域なのかを明確に理解できるようになるまでは、Anacondaを使うべきではない、と個人的には思う次第だ。


Pipenv

https://github.com/pypa/pipenv

Pipenvは、virtualenvの仕事に加えて、Pipfileという次世代のパッケージ管理システムを実装したツールである。

Pipenvは仮想環境を作成するだけでなく、pipと同じようにパッケージ管理を行うことができる。その際、pipとは異なり、「何が要求されたパッケージで、何が依存関係の解決に必要だったパッケージなのか」を記録することができる。

これによって、どのパッケージがどのパッケージによって要求され、どのパッケージによってバージョン固定されたのかがわかり、パッケージリストがきれいになるのである。

Pythonに馴染みがない人にとっては、あまり利点がわからないかもしれない。

実際、あまり開発をしないのであれば、venvで十分なのではないかという気もする。

あと、これは個人的な主観なのだが、インターフェースが非常にわかりやすい。

新しいプロジェクトで仮想環境を作りたければpipenv installとするだけ、git cloneしてきたプロジェクトに置いてあったPipfileを読み込むときもpipenv installとするだけ、pipの代わりに使うときもpipenv install <package-name>pippipenvに置き換えるだけ。大変わかりやすい。


まとめ

インタプリタ切替
パッケージ切替
パッケージインストール

pyenv

virtualenv

pip

venv

pyenv-virtualenv

virtualenvwrapper

Anaconda


Pipenv



pyenv-virtualenvをやめ、Pipenvを使う

以上の仮想環境ツールを比較した上で、私はpyenv-virtualenvをやめ、Pipenvを使うことにした。

pyenv-virtualenvをやめたことで、私のshellは爆速になった。もう二度とpyenv-virtualenvを使うつもりはない。

Pipenvはあくまでも仮想環境マネージャなので、Python自体のインストールは別の方法で行う必要がある。

pyenvに任せてもいいのだが(実際、Pipenvにはpyenvと協調する仕組みがある)、pyenvのやってくれることのうち「状況に応じて適切なPythonインタプリタを用いられる」という部分はPipenvがすでに担当しており、仕事が被ってしまうと思ったので、Pythonは手動でインストールすることにした。

実際、普通の人間に必要なPythonは最新バージョンのstableなpython(現時点では3.7.3)だけであり、あとは時々3.6や3.5、考古学者のために2.7が必要になるくらいである。Pyenvのような強いシステムの出る幕はたぶんない。

Pipenvのインストールは単純で、公式ページに書かれている通り、brewaptで入れたり、あるいはpython -m pip install --user pipenvとするだけである。

新しくプロジェクトを立ち上げる際には、

~$ mkdir project1  # Projectを作成

~$ cd project1 # Projectに移動
~/project1$ pipenv install # 仮想環境を作成
~/project1$ pipenv shell # 仮想環境に入る

とすればよい。

次からは単にpipenv shellとするだけである。


おわりに

この記事では、pyenvvirtualenvpipvenvpyenv-virtualenvvirtualenvwrapperAnacondaPipenvを並べ、それらの特性について軽くまとめた。

この記事が皆さんのPythonライフの一助となれば幸いである。

Pipenv流行れ。