この記事に記載されているpoetry installコマンドは、2024/01/16(numpyの最新バージョンが1.26.3のとき)に実行しました。
環境
- Python 3.12.1
- poetry 1.7.1
やりたいこと
Python3.8~3.12で動くツールを作りたいです。依存ライブラリはnumpyを利用します。
poetryで依存ライブラリを管理したいので、以下のpyproject.tomlを定義しました。
[tool.poetry]
name = "install-test-312"
version = "0.1.0"
description = ""
authors = ["yuji38kwmt"]
readme = "README.md"
packages = [{include = "install_test_312"}]
[tool.poetry.dependencies]
python = "^3.8"
numpy = "*"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
何が起きたか
Python3.12環境でpoetry installを実行したら、エラーが発生しました。
$ poetry install
Updating dependencies
Resolving dependencies... (0.8s)
Package operations: 1 install, 0 updates, 0 removals
  • Installing numpy (1.24.4): Failed
  ChefBuildError
  Backend 'setuptools.build_meta:__legacy__' is not available.
  
  Traceback (most recent call last):
    File "/home/vagrant/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pyproject_hooks/_in_process/_in_process.py", line 77, in _build_backend
      obj = import_module(mod_path)
            ^^^^^^^^^^^^^^^^^^^^^^^
    File "/home/vagrant/.pyenv/versions/3.12.1/lib/python3.12/importlib/__init__.py", line 90, in import_module
      return _bootstrap._gcd_import(name[level:], package, level)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
    File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
    File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
    File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
    File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
    File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 994, in exec_module
    File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
    File "/tmp/tmp_2lnurl6/.venv/lib/python3.12/site-packages/setuptools/__init__.py", line 10, in <module>
      import distutils.core
  ModuleNotFoundError: No module named 'distutils'
  
  at ~/.pyenv/versions/3.12.1/lib/python3.12/site-packages/poetry/installation/chef.py:164 in _prepare
      160│ 
      161│                 error = ChefBuildError("\n\n".join(message_parts))
      162│ 
      163│             if error is not None:
    → 164│                 raise error from None
      165│ 
      166│             return path
      167│ 
      168│     def _prepare_sdist(self, archive: Path, destination: Path | None = None) -> Path:
Note: This error originates from the build backend, and is likely not a problem with poetry but with numpy (1.24.4) not supporting PEP 517 builds. You can verify this by running 'pip wheel --no-cache-dir --use-pep517 "numpy (==1.24.4)"'.
numpy 1.24.4のインストールで失敗したようです。
原因
エラーメッセージには
This error originates from the build backend, and is likely not a problem with poetry but with numpy (1.24.4) not supporting PEP 517 builds.
とあるのでpoetryではなくnumpyの問題のようです。
The Python versions supported by this release are 3.8-3.11.
と書いてありました。したがって、Python3.12に対応していないnumpy1.24.4をインストールしようとしたことがエラーの原因のようです。
ではなぜ、poetryはPython3.12に対応していないnumpy 1.24.4をインストールしようとしたのでしょうか?
numpy1.24.4のsetup.pyにはpython_requires>=3.8と記載されています。1python_requires>=3.8,<3.12とは記載されていません。したがって、poetryはnumpy 1.24.4がPython3.12に対応していないことが分からず、numpy 1.24.4のインストールを試みたようです。
def setup_package():
    ...
    metadata = dict(
        ...
        python_requires='>=3.8'
そして、numpy1.25以降はPython3.12に対応していますがPython3.8には対応していません。
poetryはnumpyの最新バージョン1.26.3から1つずつバージョンを下げていき、Python3.8以上に対応しているかを確認していきます。
Python3.8に対応している最新のnumpyバージョンが1.24.4だったので、numpy1.24.4をインストールしたようです。
poetry installに-vvvオプションを指定すると、バージョンを1つずつ下げる挙動を確認できました。
$ poetry install -vvv
Loading configuration file /home/vagrant/.config/pypoetry/config.toml
Loading configuration file /home/vagrant/.config/pypoetry/auth.toml
Using virtualenv: /home/vagrant/Documents/study/python3.12/install-test-3.12/.venv
Updating dependencies
Resolving dependencies...
   1: fact: install-test-312 is 0.1.0
   1: derived: install-test-312
   1: fact: install-test-312 depends on numpy (*)
   1: selecting install-test-312 (0.1.0)
   1: derived: numpy
[keyring.backend] Loading KWallet
[keyring.backend] Loading SecretService
[keyring.backend] Loading Windows
[keyring.backend] Loading chainer
[keyring.backend] Loading libsecret
[keyring.backend] Loading macOS
Creating new session for pypi.org
Source (PyPI): 103 packages found for numpy *
   1: fact: numpy (1.26.3) requires Python >=3.9
   1: derived: not numpy (==1.26.3)
   1: fact: numpy (1.26.2) requires Python >=3.9
   1: derived: not numpy (==1.26.2)
   1: fact: numpy (1.26.1) requires Python <3.13,>=3.9
   1: derived: not numpy (==1.26.1)
   1: fact: numpy (1.26.0) requires Python <3.13,>=3.9
   1: derived: not numpy (==1.26.0)
   1: fact: numpy (1.25.2) requires Python >=3.9
   1: derived: not numpy (==1.25.2)
   1: fact: numpy (1.25.1) requires Python >=3.9
   1: derived: not numpy (==1.25.1)
   1: fact: numpy (1.25.0) requires Python >=3.9
   1: derived: not numpy (==1.25.0)
   1: selecting numpy (1.24.4)
   1: Version solving took 0.381 seconds.
   1: Tried 1 solutions.
Finding the necessary packages for the current system
Source (PyPI): 1 packages found for numpy *
Package operations: 1 install, 0 updates, 0 removals
  • Installing numpy (1.24.4): Pending...
...
ModuleNotFoundError: No module named 'distutils'のエラーについて
poetry installのエラーメッセージに、ModuleNotFoundError: No module named 'distutils'というメッセージがあります。numpy 1.24.4のインストールに失敗する原因は、このエラーです。
Python 3.12からdistutilsを利用できなくなったため、このエラーが発生しました。2
解決方法
Pythonのバージョンごとに、numpyのバージョンを指定すればpoetry installが実行できました。
numpy = [
  {version = ">=1.26", python = ">=3.9"},
  {version = "<1.25", python = "=3.8"}
]
$ poetry install -vvv
Loading configuration file /home/vagrant/.config/pypoetry/config.toml
Loading configuration file /home/vagrant/.config/pypoetry/auth.toml
Using virtualenv: /home/vagrant/Documents/study/20240201/312-gte38-for-numpy/.venv
Updating dependencies
Resolving dependencies...
   1: fact: install-test-312 is 0.1.0
   1: derived: install-test-312
   0: Duplicate dependencies for numpy
   0: Different requirements found for numpy (>=1.26) with markers python_version >= "3.9" and numpy (<1.25) with markers python_version == "3.8".
   1: Version solving took 0.007 seconds.
   1: Tried 1 solutions.
   0: Retrying dependency resolution with the following overrides ({Package('install-test-312', '0.1.0'): {'numpy': <Dependency numpy (>=1.26)>}}).
   1: fact: install-test-312 is 0.1.0
   1: derived: install-test-312
   1: fact: install-test-312 depends on numpy (>=1.26)
   1: selecting install-test-312 (0.1.0)
   1: derived: numpy (>=1.26)
   1: selecting numpy (1.26.3)
   1: Version solving took 0.451 seconds.
   1: Tried 1 solutions.
   0: Retrying dependency resolution with the following overrides ({Package('install-test-312', '0.1.0'): {'numpy': <Dependency numpy (<1.25)>}}).
   1: fact: install-test-312 is 0.1.0
   1: derived: install-test-312
   1: fact: install-test-312 depends on numpy (<1.25)
   1: selecting install-test-312 (0.1.0)
   1: derived: numpy (<1.25)
   1: selecting numpy (1.24.4)
   1: Version solving took 0.015 seconds.
   1: Tried 1 solutions.
   0: Complete version solving took 0.473 seconds with 2 overrides
   0: Resolved with overrides: ({Package('install-test-312', '0.1.0'): {'numpy': <Dependency numpy (>=1.26)>}}), ({Package('install-test-312', '0.1.0'): {'numpy': <Dependency numpy (<1.25)>}})
Finding the necessary packages for the current system
Package operations: 1 install, 0 updates, 0 removals
  • Installing numpy (1.26.3)
Writing lock file
Installing the current project: install-test-312 (0.1.0)
  - Building package install-test-312 in editable mode
  - Adding install_test_312.pth to /home/vagrant/Documents/study/20240201/312-gte38-for-numpy/.venv/lib/python3.12/site-packages for /home/vagrant/Documents/study/20240201/312-gte38-for-numpy
  - Adding the install_test_312-0.1.0.dist-info directory to /home/vagrant/Documents/study/20240201/312-gte38-for-numpy/.venv/lib/python3.12/site-packages
numpy 1.26.3がインストールされました。
ちなみに、poetry.lockには以下のようにnumpyの情報が複数記載されていました。
[[package]]
name = "numpy"
version = "1.24.4"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.8"
files = [...]
[[package]]
name = "numpy"
version = "1.26.3"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.9"
files = [...]
さらに補足ですが、poetry buildで生成されたwheelファイル内のMETADATAファイルには、以下のようにnumpyのバージョンが記載されていました。
Requires-Dist: numpy (<1.25) ; python_version == "3.8"
Requires-Dist: numpy (>=1.26) ; python_version >= "3.9"
注意:poetry1.7.1でのpoetry show numpyの結果は正しくない
poetry installのログにはInstalling numpy (1.26.3)と出力されました。
しかしpoetry showコマンドでは"numpy 1.24.4"と出力されました。
$ poetry show numpy
 name         : numpy                                             
 version      : 1.24.4                                            
 description  : Fundamental package for array computing in Python 
詳細は別記事に記載しました。
- 
wheelファイルに含まれる numpy-1.24.4.dist-info/METADTAのRequires-Python: >=3.8に相当します。 ↩
