はじめに
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
流行れ。