direnvとconda利用者の悩み
direnvは現在いるディレクトリに応じて環境変数を切り替えてくれるツールである。これを使うとAnaconda利用者の悩みであった、システムのPythonなどがAnacondaのものでPathが隠されてしまうことが回避できる。
これまでAnacondaを利用する際にはこのPathの無差別な覆いを防ぐために、pyenvなどを通してCondaを利用することが多かった。一方でpyenvはそもそもPythonの複数バージョンを管理するツールで、インストールしたpythonバイナリ自体を管理されてしまい、よくわからない挙動をすることも多く、扱いにくいところもあった。
Qiita: pyenvが必要かどうかフローチャート
pyenv経由でAnacondaをインストールするメリット
condaの利用者がみんなよってたかってpyenvを利用するようになった結果、condaもpyenvもいらないような人が巻き込まれたりしたようだ。Anacondaの公式サイトではインストールの後に、activate/deactivateでpathの問題は切り替えろ!と書いてあり、そんなことしてられるか!という感じである。先日JuliaTokyoに参加した際に、@bicycle1885さんがdirenvというツールがあることを教えてくれた。
講演のスライド: 覇権を取るパッケージ作成 佐藤健太@bicycle1885
私は普段Juliaしか使わないのでこのcondaの話とは無縁だったのだが、研究室の仲間たちがこれでややこしいことに巻き込まれているのを救うためにも、Pythonの人たちのために記事を書いておく。
今まで私のMacの環境では、
brew -> pyenv -> conda
としていたところを、
brew -> direnv
公式サイト -> conda
として組み合わせて利用する。
以下、macOSでの手順を書くが、他のOSでも似たような手順でdirenvでcondaを分離しておくことはできるはずだ(必要性があるかどうかは知らないが)。
direnvでcondaを利用する手順
1. brew
まずdirenvをインストールするためにHomebrewを入れる。MacPortsにもdirenvはあるようだ。brewを使いたくない人は別の方法でインストールすれば良い。
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2. direnv
brewでdirenvをインストールする。
brew install direnv
インストールされたかどうか確認する。
direnv
direnvの公式サイトのsetupの項目にあるように、
bashなら
# ~/.bashrc
eval "$(direnv hook bash)"
fishなら
# ~/.config/fish/config.fish
eval (direnv hook fish)
とする。他のシェルはサイトを見ること。
3. conda (anaconda か miniconda)
Anacondaの公式サイトからAnacondaかMinicondaをインストールする。私はMinicondaを入れた体験に基づいてこの記事を書いている。Anacondaの人は適宜Minicondaに読み替えて欲しい。
以下の公式サイトの手順に従うが、
インストール時の設定の際に、環境変数の設定するかと聞かれたらnoにしておく。自分でそこを管理するのが目的なので。インストールする場所は個人的に見えるのが嫌なので、デフォルトだと~/minoconda
のものを~/.miniconda
に置いている。
インストールが完了したら、
# インストール場所がデフォルトなら
~/miniconda/bin/python
# 私は場所を変えているので
~/.miniconda/bin/python
としてインストールされたバイナリがちゃんと起動するかどうか確認する。
↪ ~/.miniconda/bin/python
Python 3.7.0 (default, Jun 28 2018, 07:39:16)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
確認したらexit()
としてPythonを終了する。
4. direnvで動的にcondaのバイナリをpathに追加
このままだとminicondaのpythonを呼び出すたんびに、~/miniconda/bin/python
と打つ必要があるので、$HOME/miniconda/bin
を環境変数PATH
に追加したいが、
# bashなら~/.barhrc
# miniconda
export PATH=$HOME/miniconda/bin:$PATH
# fishなら~/.config/fish/config.fish
# miniconda
set -x PATH $HOME/miniconda/bin $PATH
そのまま追加するとシステムのバイナリたち/usr/local/bin/python
とかを覆って見えなくしてしまうので、direnvを使う。Minicondaを利用したい作業ディレクトリのルートに、.envrc
を置き、そこに設定を書けば良い。
例えば、~/work
以下のディレクトリでminicondaで覆ってしまう場合は、
# ~/work/.envrc
# miniconda
export PATH=$HOME/miniconda/bin:$PATH
とすれば良い。このとき、.envrc
の設定はbashで書かなければならないことに注意する(fishなどの他のシェルを使っていても)。行った.envrc
の変更を許可し、
direnv allow ~/work/.envrc
シェルを再起動して、cd ~/work
とすれば、
paalon at mac in ~
↪ python
Python 2.7.14 (default, Mar 22 2018, 14:43:05)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
paalon at mac in ~
↪ cd work
direnv: loading .envrc
direnv: export ~PATH
paalon at mac in ~/work
↪ python
Python 3.7.0 (default, Jun 28 2018, 07:39:16)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
paalon at mac in ~/work
↪
これによってpyenvの覆い効果と同等のことがdirenvでできる。
まとめ
これによって(ana or mini)conda利用者はpyenvから開放されることになり上記のような疑問はdirenvによって解決されることになる。direnvを利用するメリットとしては、pyenvはその内蔵のcondaだけ使っている場合は特に不便を感じないのだが、他のものと組み合わせて利用しようとするときに、融通が効かなくて困ることが多かった。Anaconda特有の環境変数マスクを解決する場合にはpyenvよりもdirenvの方が目的にかなっておりスマートであると私は思っている。(PythonなんかよりJuliaの方が便利だということは置いておいたとして…)