はじめに
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系の中でも互換性のない変更はたくさん行われているし、あるいはPyPyやIronPythonといった(よく知られた)Pythonとは異なる実装のインタプリタもある。
つまり、我々はたくさんのPythonを持っていて、それらをプロジェクトに応じて適切に切り替えなければならない。
また、Pythonには様々なパッケージがある。開発者はこれらを好き勝手にインストールして使うわけだが、もちろんこれらのパッケージにもバージョンや互換性の問題は存在する。「このプロジェクトは、このパッケージをインストールしないと動きません。ただし、バージョンxx以上yy以下です。」という注意書きがすべてのプロジェクトに存在しており、それらをうまく扱うためにはパッケージのバージョンを切り替えてくれるツールが当然必要だ。
そういうわけで、我々は2つのものごとについて仮想環境を必要としている。
すなわち、Pythonインタプリタ本体と、パッケージ群である。
まとめ
| インタプリタ切替 | パッケージ切替 | パッケージインストール | |
|---|---|---|---|
| pyenv | ○ | ||
| virtualenv | ○ | ○ | |
| pip | ○ | ||
| venv | ○ | ||
| pyenv-virtualenv | ○ | ○ | |
| virtualenvwrapper | ○ | ||
| Anaconda | ○ | ○ | △ |
| Pipenv | ○ | ◎ |
pyenv
pyenvは、前述した2つのうち前者のみを担当する仮想環境マネージャである。
pyenvのやることは以下の通りである:
-
$PATHの先頭にPYENV/shimsを挿入し、あらゆるPython系コマンドへのアクセスに割り込む。 - いま動かすべき
Pythonインタプリタを探す。 - 受け取ったコマンド(例えば
python main.py、pip3 install -r)を、その探したインタプリタに投げる。
すなわち、諸々のコマンドを適切な窓口に振り分ける、受付係を引き受けてくれるのである。
適切なインタプリタを探すために、pyenvは以下の操作を行う:
- もし環境変数
PYTHON_VERSIONが設定されていれば、そのバージョンに従う。 - そうでなければ、今のディレクトリから順に親ディレクトリを遡っていく。その途中で
.python_versionファイルが見つかれば、そこに書かれているバージョンに従う。 - ルートまで遡っても見つからなければ、グローバルに設定されているバージョンに従う。
こうすることで、今いるプロジェクトにとって最も適切なPythonを起動することができるのである。
結局、Pyenvを用いる利点は以下の通り:
- 状況に応じて適切な
Pythonインタプリタを、手動で切り替えることなく用いられる。 - いろいろな
Pythonインタプリタを、コマンド一発でインストール・アンインストールできる。
virtualenv
virtualenvは、前述した2つの両方、すなわちPythonインタプリタとパッケージ群を同時に切り替えられる仮想環境マネージャである。
virtualenvは、ENV/以下にPythonインタプリタ、インストールされたパッケージなどすべてを保存している。そして、source ENV/bin/activateを行うと(これがvirtualenvを使うための魔法の呪文である)、その仮想環境のフォルダにパスが通る。これ以上のことは何もしない。
いちいち仮想環境の場所を探してactivateしなければならないという面倒臭さはあるものの、動作は単純明快であり、環境が分離されていることもわかりやすい。ただし、pyenvとは異なり、新しいPythonをインストールしたりはできないので注意が必要である。あくまでも$PATHを探してPythonを見つけ、そのインタプリタをコピーするだけである。
結局、virtualenvを用いる利点は以下の通りである:
-
Pythonインタプリタとパッケージの組み合わせを好きなだけ作り、分離することができる。 - それらを
activateで切り替えることができる。
pip
pipは、Python公式のパッケージ管理ツールである。
Pythonを知っている人であれば、この並びにpipが居るのはおかしいと思うかもしれない。
実際、pipはPythonインタプリタを切り替えてはくれないし、パッケージの仮想環境を作ってくれるわけでもない。
pipがすることは、Pythonのパッケージを探し、適切なバージョンのパッケージを、依存関係を解決しながらインストールすることである。
venvやpyenv-virtualenvなど、多くの仮想環境ツールはpipを使ってパッケージをインストールすることを想定している。
pipでインストールしたパッケージは、requirements.txtという形で共有することができる。
このrequirements.txtには、必要に駆られてインストールしたパッケージのほか、依存関係の解決に必要だったパッケージ、開発時に必要だったlinterパッケージなどもすべて記述されている。
別の環境でそのプロジェクトを実行したければ、適当な仮想環境の下でpip install -r requirements.txtとすれば、それらのパッケージが全てインストールされ、元と同じ環境で実行できるというわけだ。
ここでpipを紹介した理由は、もちろん、このあとpipの仕事を代替するツールが登場するからである。
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を用いることができる。 -
virtualenvのactivateによるバージョンの切り替えを、手動で切り替えることなく用いられる。
venv (旧称: pyvenv)
venvは、Python公式が提供する仮想環境マネージャである。
その挙動はvirtualenvとあまり変わらない。
公式が提供しているのだし、virtualenvを生で使うくらいならこっちを使うのがいいのではないだろうか。
virtualenvwrapper
virtualenvwrapperは、何かと使い勝手の悪いvirtualenvの動作を隠蔽し、変なことをしないようにするラッパーである。
使ったことがないのであんまりわからないが、おとなしくvenvを使っておけばいいと思う。
Anaconda (, miniconda, conda)
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
Pipenvは、virtualenvの仕事に加えて、Pipfileという次世代のパッケージ管理システムを実装したツールである。
Pipenvは仮想環境を作成するだけでなく、pipと同じようにパッケージ管理を行うことができる。その際、pipとは異なり、「何が要求されたパッケージで、何が依存関係の解決に必要だったパッケージなのか」を記録することができる。
これによって、どのパッケージがどのパッケージによって要求され、どのパッケージによってバージョン固定されたのかがわかり、パッケージリストがきれいになるのである。
Pythonに馴染みがない人にとっては、あまり利点がわからないかもしれない。
実際、あまり開発をしないのであれば、venvで十分なのではないかという気もする。
あと、これは個人的な主観なのだが、インターフェースが非常にわかりやすい。
新しいプロジェクトで仮想環境を作りたければpipenv installとするだけ、git cloneしてきたプロジェクトに置いてあったPipfileを読み込むときもpipenv installとするだけ、pipの代わりに使うときもpipenv install <package-name>とpipをpipenvに置き換えるだけ。大変わかりやすい。
まとめ
| インタプリタ切替 | パッケージ切替 | パッケージインストール | |
|---|---|---|---|
| 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のインストールは単純で、公式ページに書かれている通り、brewやaptで入れたり、あるいはpython -m pip install --user pipenvとするだけである。
新しくプロジェクトを立ち上げる際には、
~$ mkdir project1 # Projectを作成
~$ cd project1 # Projectに移動
~/project1$ pipenv install # 仮想環境を作成
~/project1$ pipenv shell # 仮想環境に入る
とすればよい。
次からは単にpipenv shellとするだけである。
おわりに
この記事では、pyenv、virtualenv、pip、venv、pyenv-virtualenv、virtualenvwrapper、Anaconda、Pipenvを並べ、それらの特性について軽くまとめた。
この記事が皆さんのPythonライフの一助となれば幸いである。
Pipenv流行れ。