現象
pip コマンドを実行すると、 pkg_resources.DistributionNotFound: pip==1.5.4
のようなエラーが表示されて何もできない。
再現手順
- Homebrew で Python をインストールする
- 新しい pip がある状態で
pip install --upgrade pip
する
brew install python
すると、
==> Caveats
Setuptools and Pip have been installed. To update them
pip install --upgrade setuptools
pip install --upgrade pip
のように表示されるのですが、この通りに pip をアップグレードすると pip が動かなくなります。
pip がアップグレードされたのに /usr/local/bin/pip
が古いままになっている状態です。
対処
python -m pip
で pip を起動できます。 /usr/local/bin/pip
を削除して
$ rm /usr/local/bin/pip /usr/local/bin/pip2 /usr/local/bin/pip2.7
$ python -m pip install --upgrade --force-reinstall pip
もしくは
$ python -m pip install --upgrade --force-reinstall pip --no-use-wheel
をします。
後者の方法を利用する場合は、今後 pip や setuptools を upgrade する際は常に
$ pip install --upgrade --no-use-wheel pip setuptools
する必要があります。
原因
Homebrew と wheel の相性問題です。
Homebrew は Python をインストールする際に、 pip と setuptools を
/usr/local/Cellar/python/<version>/
配下にインストールし、 /usr/local/bin/
に pip コマンドなどへの symlink を設置します。
そして、 distutils.cfg
に prefix=/usr/local
という設定を書き、通常 pip install
などでインストールされるパッケージが /usr/local/bin/
配下にスクリプトが、 /usr/local/lib/pytthon2.7/
配下にライブラリがインストールされるようにします。
この状態で pip install --upgrade pip
すると、 /usr/local/bin/pip
スクリプトをインストールしたいのですが、そこにはすでに Homebrew が勝手に作った pip が感知しない symlink が存在します。
スクリプトをインストールしたい場所にすでに symlink があったときの振る舞いですが、 wheel からのインストールと tar.gz からのインストールで違っていて、 wheel の場合はインストールできずにスキップされ、 tar.gz からの場合は symlink のリンク先 (つまり Cellar の中身) を書き換えてしまいます。
最近の pip はデフォルトで wheel があるとそれを使うので、 Cellar 配下の古いバージョンの pip を使おうとするスクリプトに対する symlink がそのまま残ってしまい、起動できなくなってしまうのです。
wheel を使う場合と使わない場合で振る舞いが違うのは良くないとは思いますが、そもそも外部で勝手に作られた symlink に上書きインストールする場合の挙動に正解なんて無いので、 Homebrew は pip install --upgrade pip
を許すなら最初から普通に pip をインストールするべきだと思います。
追記
pip と setuptools を Cellar 内にインストールするのをやめるように修正する Pull request を出しました。 https://github.com/Homebrew/homebrew/pull/29926
追記2
上記の PR は Homebrew の基本方針とあわないので却下されました。
そこで、 wheel を使ったインストール時にも wheel を使わない場合と同じように、スクリプトのインストール先にすでにシンボリックリンクが合っても(リンク先を)上書きするようにする修正を pip 側に PR し、先ほど取り込まれました。
次の pip (1.6.0) がリリースされて、 Homebrew の Python にバンドルされるようになったら、その次のバージョンからは普通に pip install --upgrade pip
でアップグレードできるようになるはずです。
とは言え、 Celler の中と外で2つの pip があり、外にインストールするときに中のスクリプトを書き換えるという、到底スマートとは言えない状態です。
特に困ってるのでなければ、 pip のアップグレードは行わず、 Homebrew がアップデートされるのを待つことをお勧めします。
また、 Python のヘビーな開発者は、独自の方式のために無理やりなことをしている Homebrew よりも MacPorts や、 pyenv を使った自前ビルドの方がいいかもしれません。
pip install --upgrade pip
は直りましたが、 pip install --user ipython
とかは動かないままですし、パッケージング周りで他にどんな副作用があるかも解りません。