(~~この記事は将来解決されているはずです。そのときに無駄記事にならないように試行錯誤の内容などを残しておきます。~~最近pipenvの開発状況が怪しく、ここに書いた方法で動作しない可能性があります。トラブルシューティングの例として見てください(2019/12/24追記)。)
経緯
tensorflow2.0のリリースが待っている間、tensorflow2.0のnightlyビルド(tf-nightly-2.0-preview)で素振りをしている今日この頃です。
さて、パッケージの管理にpipenvを使っているのですが、前のnightlyビルドのインストールから日が経っていたので、更新しようと思いました。しかし、これが上手く行かず、がちゃがちゃしたというのがこの記事の話です。
解決策
まず、原因から。今pypiに公開されているpipenv(バージョン2018.11.26)はXX-manylinux2010_x86_64.whlというファイル名のwheelに対応しておらず、tf-nightly-2-0-previewがこのタイプのwheelになっていました。
ということで、対策済みpipenvをインストールすればいいです。githubにあるpipenvのmasterブランチは対策済みだったので、これを使えばよく、これで解決できます。
コマンドにすると、こんな感じです。
$ pip install git+https://github.com/pypa/pipenv.git
$ pipenv update --pre --dev
いや、まあ、「pipenv公式さん、更新はよ」ってことなんですが・・・
注意時項ですが、pyenv virtualenvで作った環境でこれをすると上手く行かなかったです。pyenv local 3.X.X
でバージョンを指定してそこにpipenvをインストールする普通のpyenvの使い方をすれば、問題無く出来ました。上の方法が上手く行かなかったら参考にしてください。
試行錯誤
ざっくりと次のステップで原因を突き止めました。
- Pipfileの問題箇所の特定(tf-nightly-2.0-preview)
- 同じ問題が発生する最初のtf-nightly-2.0-previewのバージョンの特定(8月2日版からおかしい)
- 8月1日版と8月2日版の比較(wheelの名前が違う)
- wheelの問題かpipenvの問題かの切り分け(pipenvが悪いと判明)
- pipenvのソースコードで"manylinux"を検索(2019年3月にmanylinux2010の対策がされていることを発見)
- 解決策の方法を確かめる
それぞれどんな感じだったかについて紹介します。
Pipfileの問題箇所の特定
遊んでみようという意図の趣味プロジェクトなので、僕のPipfileには、githubの特定のブランチから取ってくるものやnightlyビルドの怪しげなものが書かれています。そんな怪しいものを一つずつコメントアウトしてpipenv install --pre --dev
が通るかを確認しました(エラーログも大して参考にならなかったりもして・・・)。
そうやってすぐ、tf-nightly-2.0-previewが悪いことが分かりました。
同じ問題が発生する最初のtf-nightly-2.0-previewのバージョンの特定
前回は正しく動いていたので、バージョンの問題だろうと考えました。まず、前回と同じくらい(7月14日版)のバージョンを指定しました。これは無事インストール出来ました。今度は「ここが怪しい」というような勘が効かない上、nightlyビルドは日毎に新しいバージョンがあるので、(雑)バイナリサーチの出番です。
8/15:失敗、7/14:成功、8/1:成功、8/7:失敗、・・・というように探索して8月2日版からおかしいことを突き止めました(ちゃんと2分する日を選んでないのは計算をサボっただけです)。
8月1日版と8月2日版の比較
比較しようにもどうすれば・・・となった部分です。なにはともあれブツが無いとどうしようも無いので、pip download
コマンドを使ってwheel等をダウンロードします。
$ mkdir 801
$ cd 801
$ pip download tf-nightly-2.0-preview==2.0.0.dev20190801
$ cd ..
$ mkdir 802
$ cd 802
$ pip download tf-nightly-2.0-preview==2.0.0.dev20190802
$ cd ..
ブツをダウンロードして、まず、ファイル名を比較することにしました。これをすると依存パッケージが違うという予想でこれをしたのですが、結果は別のものでした。8月2日版からXX-manylinux2010_x86_64.whlというファイル名に変わっていたのです。
$ ls 801 > 801.txt
$ ls 802 > 802.txt
$ diff 801.txt 802.txt
19c19
< tf_nightly_2.0_preview-2.0.0.dev20190801-cp37-cp37m-manylinux1_x86_64.whl
---
> tf_nightly_2.0_preview-2.0.0.dev20190802-cp37-cp37m-manylinux2010_x86_64.whl
wheelの問題かpipenvの問題かの切り分け
tensorflowには、python3.7対応を中々しなかったという前科があるので、まーたビルド手順サボって特定の環境で使えないwheelをアップロードしているんじゃないのかと思いました。
そんな疑念のもと、まず、manylinux2010についてググりました。どうやらPEP571でこのようなタグが登場したことが分かりましたが、長い説明で、読むのは諦めました。
知りたいのは僕のPCで使えるのかどうかです。なので、純粋な環境(pipenvと関係のない環境)でインストール出来るかを試しました。これが分かると原因がwheelかpipenvかのどちらかに絞れます。やり方は単純にpipでインストールしてみるだけです。無事インストールできたので、悪いのはpipenvということが分かりました。
$ pip download tf-nightly-2.0-preview==2.0.0.dev20190802
pipenvのソースコードで"manylinux"を検索
pypiにあるpipenvの最新版は2018年11月にリリースされたものです。ナウいツールとして使われている割にはリリース頻度が低いという心象をpipenvには持っていました。
pipenvの前回リリースからかなり経っているので、誰かissueにしたりとか、もう解決しているんじゃないかと予想しました。ファイル名が変わって問題が出るってことは、雑にファイル名で判定しているんじゃないかなとも思えたので、おもむろに"manylinux"で検索しました。
結果としては、pipenv/patched/notpip/_internal/pep425tags.pyに、is_manylinux1_compatible
やis_manylinux2010_compatible
という関数があってそれで判定をしていることが分かりました。
is_manylinux2010
といういかにもな関数が見つかったので、これが追加された時期が最近ならmasterブランチを試す価値があります。調べてみると2019年3月のようなので、pypiにあるpipenvは未対応のバージョンでmasterブランチを試す価値ありと判明しました。
manylinux2010
検索のために、ローカルにcloneしてgit grep manylinux2010
したり、is_manylinux2010
の追加日の特定にtig pipenv/patched/notpip/_internal/pep425tags.py
みたいなことを僕はしましたが、よく考えれば、github上で検索や履歴の確認が出来るのでそっちの方がいいかも知れません。
そんな感じでpipenvをmasterブランチのものにして問題は解決しました。めでたしめでたし。