numpy が pip 経由なら入るのに poetry 経由だと入らない時の一解決案

## TL;DR

### 想定する状況

- numpy がシステムの pip3 経由だと `pip3 install numpy` で問題なく入るのに
- poetry 経由で `poetry add numpy` するとエラーが出てしまう

### 解決案
1. `poetry run pip install numpy` を叩いて、poetry の作った仮想環境の中で pip3 経由で `numpy` を半ば無理矢理放り込む
2.  `poetry add numpy` を叩いて、poetry に numpy を認識させ、`pyproject.toml` と `poetry.lock` を更新する

補足：手元の環境でこのステップを実行したのは2021年1月20日です。

### 解決案その2（2021年2月18日追記）
どうも poetry のコンフィグの1つ `experimental.new-installer` が悪さをしているらしく、

```
poetry config experimental.new-installer false
```

として、並列にパッケージをインストールする新しいインストーラを無効化すると、通常の `poetry add numpy` だけでうまくいくようです。
c.f. https://github.com/python-poetry/poetry/issues/3196

## 環境
- OS: macOS Big Sur 11.1
- Python: 3.9.1 (Homebrew 2.7.5 より)
- pip3 20.3.3 (上記Python 3.9.1に付随)
- Poetry: 1.1.4

## 解決までの道筋

### 失敗：numpy1.20.0rc を入れてみる
https://github.com/numpy/numpy/issues/17987#issuecomment-75202322 を見ると

> You can use the 1.20.0rc2 release candidate.
> `python -m pip install -i https://pypi.anaconda.org/multibuild-wheels-staging/simple numpy==1.20.0rc2`
> This should become the 1.20.0 release in a few weeks.

という記述があるので、`poetry add numpy==1.20.0rc2` を試してみます。
しかしながら、インストール時のビルドの過程で AssetionErrorが出てしまい、この道は諦めることとしました。

### 失敗：Pythonのバージョンを 3.8 に落とす
https://numpy.org/news/ によれば、Python3.9 向けの numpy のバイナリは 2020年9月14日 時点ではまだ準備中とのことです。もしかするとこれが影響していて、Python3.9 の環境では、poetry 経由だとソースコードからビルドしようとしているから失敗しているのではないかと予想しました。Python3.8にバージョンを落として試してみました。

> PYTHON 3.9 IS COMING, WHEN WILL NUMPY RELEASE BINARY WHEELS?
> Sept 14, 2020 – Python 3.9 will be released in a few weeks. If you are an early adopter of Python versions, you may be dissapointed to find that NumPy (and other binary packages like SciPy) will not have binary wheels ready on the day of the release. It is a major effort to adapt the build infrastructure to a new Python version and it typically takes a few weeks for the packages to appear on PyPI and conda-forge. In preparation for this event, please make sure to

> - update your pip to version 20.1 at least to support manylinux2010 and manylinux2014
> - use `--only-binary=numpy` or `--only-binary=:all:` to prevent pip from trying to build from source.

結論だけ言うと、この予想は誤りで、2021年1月20日現在では Python3.9 向けの numpy のバイナリが配布されていました ( https://pypi.org/project/numpy/#files )。Python のバージョンを下げても最初から意味はなかったわけです。残念。

### 成功 (step1) ：システムの pip3 経由だと問題なくインストールできることに立ち返る
冒頭で以下の事前条件を書きました。
> numpy がシステムの pip3 経由だと `pip3 install numpy` で問題なく入るのに

試行錯誤の中で、numpy を poetry 経由でなく pip3 経由で入れて入るかどうか試す時があったのですが、手元の環境ではシステムのpip3 経由であれば numpy が問題なくインストールできていました。そうであるならば、poetry の仮想環境の中で poetry を使わずに pipで numpyを入れてしまうということはできないかと思い立ったのです。
つまりは、

```
poetry run pip install numpy
```

こういうことです。若干嫌な感じもしますが、ものは試しということでやってみました。

すると、なんと問題なく入るではありませんか！

### 成功 (step2) ：poetry に numpy の存在を認識させる
上記ステップで、poetry の作った仮想環境の中に、numpy が半ば無理矢理入りました。しかしながら、今試した方法は poetry の想定する通常のライブラリインストール方法とは異なるため、poetry は numpy 管理対象のパッケージとして認識していません。具体的には、`pyproject.toml` と `poetry.lock` が一切更新されていないのです。
そのため、この段階で `poetry update` などと叩こうものなら、「正体不明の」 numpy はpoetry の作った仮想環境から削除されてしまいます。

そこで、`poetry add numpy` を実行し、poetry に形式的に numpy のインストール処理をさせます。 numpy はすでに poetry の作った仮想環境の中にインストールされているので、実際には numpy インストールは実行されず、依存関係管理のファイルの更新のみを行なってくれます。

## Appendix: 類似記事
本記事としたような状況に陥って、無理矢理解決した例がすでにありました。
https://qiita.com/Ryuichirou/items/f769e5072305802e18c5

上記類似記事では、以下の手順を踏んでいるようです。

1. pip経由で システムに numpy をインストールする
2. 仮想環境を poetry に作らせず、手動で作成し、そこに pip 経由で numpy をインストールする
3. 手動で作成した仮想環境で poetry を起動し、poetry にその仮想環境を認識させる
4. poetry の初期化段階で入るべき依存関係を `requirements.txt` として poetry に吐かせる
5. pip経由で `requirements.txt` の内容をインストールさせる

類似記事の著者は自ら

> なんかコレジャナイ感がすごいです。よりよく解決したいですね。

と言っています。

本記事では、類似記事よりもステップ数が少なく単純な、よりよい解決案を提供できました。