type t (* void *)

ソフトウエアのこととか

現状のpoetryの問題とpoetry 1.5への期待

追記

Poetry 1.5.0 はリリースされました。
クリティカルなIssueがあり、コードベース修正されているのですがお手元のコードで問題が発生するなら1.5.1 を待つべきでしょう。

問題

現状のPoetry (1.4.2) は特定の使い方をしようとしたときにすごく困る部分がある。

例えば以下のようなpyproject.txt では初回のインストールは 228.9s かかった。

[tool.poetry]
name = "test"
version = "0.1.0"
description = ""
authors = ["test <test@gmail.com>"]

[tool.poetry.dependencies]
python = ">=3.9"
torch = { url = "https://download.pytorch.org/whl/cpu/torch-1.8.1%2Bcpu-cp39-cp39-linux_x86_64.whl" }
torchvision = { url = "https://download.pytorch.org/whl/cpu/torchvision-0.9.1%2Bcpu-cp39-cp39-linux_x86_64.whl"}
onnx_graphsurgeon = { version = "==0.3.16", source = "nvidia" }
onnx-simplifier = "==0.3.6"
opencv-python = "*"
Pillow = "*"
pandas = "*"
pycocotools = "*"
pytest = "*"
scikit-learn = "==1.0.1"
scipy = "*"

[tool.poetry.dev-dependencies]

[[tool.poetry.source]]
name = "nvidia"
url = "https://pypi.ngc.nvidia.com"
default = false
secondary = true


[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

ちなみに同じような記述をした requirements.txt を pip でインストールしようとするとインストール時間を含めて 40s くらいで終わる(上の時間はバージョン解決のみ)。

上の pyproject.toml が遅いのは種があって、NVIDIAが公開している pypi レポジトリを追加しているところがミソ。
NVIDIApypiのようにpypi.org以外のpypiレポジトリを追加した場合、Poetryのバージョン依存解決が非常に遅くなることが知られている。

ちなみにlockファイルが作られた後はバージョン解決はすでに終わっているので今回の話は関係がなく、高速に動作するハズ。

原因は default=false で指定したpypiレポジトリにもパッケージの探索のためにpypi.orgにしかないパッケージも都度存在するかどうか問い合わせてしまう、というもの。
poetry install -vvv 実行してみると問い合わせしたログが表示される。

ログの一部抜粋

....
[urllib3.connectionpool] Starting new HTTPS connection (1): developer.download.nvidia.com:443
[urllib3.connectionpool] https://developer.download.nvidia.com:443 "GET /compute/redist/scipy/ HTTP/1.1" 404 433
Source (nvidia): No packages found for scipy
Source (nvidia): 0 packages found for scipy *
Source (PyPI): 1 packages found for scikit-learn 1.0.1
[urllib3.connectionpool] https://developer.download.nvidia.com:443 "GET /compute/redist/scikit-learn/ HTTP/1.1" 404 433
Source (nvidia): No packages found for scikit-learn
Source (nvidia): 0 packages found for scikit-learn 1.0.1
Source (PyPI): 158 packages found for pytest *
[urllib3.connectionpool] https://developer.download.nvidia.com:443 "GET /compute/redist/pytest/ HTTP/1.1" 404 433
Source (nvidia): No packages found for pytest
Source (nvidia): 0 packages found for pytest *
Source (PyPI): 7 packages found for pycocotools *
[urllib3.connectionpool] https://developer.download.nvidia.com:443 "GET /compute/redist/pycocotools/ HTTP/1.1" 404 433
Source (nvidia): No packages found for pycocotools
Source (nvidia): 0 packages found for pycocotools *
Source (PyPI): 93 packages found for pandas *
...

ちなみにNVIDIApypiにしかないonnx_graphsurgeonをpyproject.tomlから削除すると削除すると、 依存解決のかかる時間は 6.9s まで短くなる!

解決策

Poetry 1.5 を待つ

Poetry 1.5 のリリース管理Issue

Poetry 1.5では sourceに対して secondary フィールドはDeprecatedになり、 supplemental なsourceを追加できるようになる。 supplemental に指定されたsourceは特定のPackageをインストールしようとするときにだけ使用されるようになるため、↑の問題は解決される(ハズ)。

追記

現状のmasterの1.5dev0 Candidateをビルドして使ってみると、依存解決は 10.4s で終わった。ハヤイ! sourceの記述を以下のように変更する

[[tool.poetry.source]]
name = "nvidia"
url = "https://pypi.ngc.nvidia.com"
priority = "supplemental"

poetry-private-repo-plugin を使う

github.com

このプラグインを使うと、特定のパッケージの探索に特定のsourceだけを使うことを強制できる。
Poetry 1.5を待てねぇ!という人はこちらを利用するしかないと思う。

その他

他にも1.5でダウンロード済みのはずのwhlを何回もダウンロードしてしまう問題が解決されるはずで、poetry install がより高速になることが期待できる。
何回もバージョン依存解決しないとはいえ、、、高速な方がうれしいヨネ?

エコシステムとしてのPythonは高速に依存解決を行うにはsetup.pyが不利になっている。
setup.py の中に依存ライブラリが記述されることになっている && setup.pyは当然スクリプトで動的に依存ライブラリ部分を買えるかもしれないので、setup.pyを実行してみないと依存ライブラリが何なのかわからない。

僕もよくわかっていないこと:metadataをつかえばこれをダウンロードするだけで依存ライブラリがわかるはずだけど、まだそこまで使われてない? METADATAの仕様としてPEP658があるはずなのだけど。