poetry の依存関係でエラーが発生した場合の対処
poetry の依存関係でエラーが発生した場合の対処

poetry の依存関係でエラーが発生した場合の対処

はじめに

poetry add をしているとバージョンが競合してにエラーが出る事があります

この記事ではそういった場合にどうやって依存関係を解決できるかを記載します

バージョン競合のメッセージ

例を出した方がわかりやすいので、poetry と s3fs のバージョン競合を例にする (2021年5月に書いているので、場合によっては再現はしない可能性があります)

まず boto3 を入れます

$ poetry add boto3
Using version ^1.17.69 for boto3

Updating dependencies
Resolving dependencies... (0.5s)

Writing lock file

Package operations: 5 installs, 0 updates, 0 removals

  • Installing jmespath (0.10.0)
  • Installing urllib3 (1.26.4)
  • Installing botocore (1.20.69)
  • Installing s3transfer (0.4.2)
  • Installing boto3 (1.17.69)

boto3 1.17.69botocore 1.20.69 がインストールされました

次に s3fs を入れてみようとするとエラーになります

$ poetry add s3fs
Using version ^2021.4.0 for s3fs

Updating dependencies
Resolving dependencies... (0.7s)

  SolverProblemError

  Because no versions of aiobotocore match >1.0.1,<1.0.2 || >1.0.2,<1.0.3 || >1.0.3,<1.0.4 || >1.0.4,<1.0.5 || >1.0.5,<1.0.6 || >1.0.6,<1.0.7 || >1.0.7,<1.1.0 || >1.1.0,<1.1.1 || >1.1.1,<1.1.2 || >1.1.2,<1.2.0 || >1.2.0,<1.2.1 || >1.2.1,<1.2.2 || >1.2.2,<1.3.0 || >1.3.0
   and aiobotocore (1.0.1) depends on botocore (>=1.15.32,<1.15.33), aiobotocore (>=1.0.1,<1.0.2 || >1.0.2,<1.0.3 || >1.0.3,<1.0.4 || >1.0.4,<1.0.5 || >1.0.5,<1.0.6 || >1.0.6,<1.0.7 || >1.0.7,<1.1.0 || >1.1.0,<1.1.1 || >1.1.1,<1.1.2 || >1.1.2,<1.2.0 || >1.2.0,<1.2.1 || >1.2.1,<1.2.2 || >1.2.2,<1.3.0 || >1.3.0) requires botocore (>=1.15.32,<1.15.33).
  And because aiobotocore (1.0.2) depends on botocore (>=1.15.32,<1.15.33), aiobotocore (>=1.0.1,<1.0.3 || >1.0.3,<1.0.4 || >1.0.4,<1.0.5 || >1.0.5,<1.0.6 || >1.0.6,<1.0.7 || >1.0.7,<1.1.0 || >1.1.0,<1.1.1 || >1.1.1,<1.1.2 || >1.1.2,<1.2.0 || >1.2.0,<1.2.1 || >1.2.1,<1.2.2 || >1.2.2,<1.3.0 || >1.3.0) requires botocore (>=1.15.32,<1.15.33).
  And because aiobotocore (1.0.3) depends on botocore (>=1.15.32,<1.15.33)
   and aiobotocore (1.0.4) depends on botocore (>=1.15.32,<1.15.33), aiobotocore (>=1.0.1,<1.0.5 || >1.0.5,<1.0.6 || >1.0.6,<1.0.7 || >1.0.7,<1.1.0 || >1.1.0,<1.1.1 || >1.1.1,<1.1.2 || >1.1.2,<1.2.0 || >1.2.0,<1.2.1 || >1.2.1,<1.2.2 || >1.2.2,<1.3.0 || >1.3.0) requires botocore (>=1.15.32,<1.15.33).
  And because aiobotocore (1.0.5) depends on botocore (>=1.15.32,<1.15.33)
   and aiobotocore (1.0.6) depends on botocore (>=1.15.32,<1.15.33), aiobotocore (>=1.0.1,<1.0.7 || >1.0.7,<1.1.0 || >1.1.0,<1.1.1 || >1.1.1,<1.1.2 || >1.1.2,<1.2.0 || >1.2.0,<1.2.1 || >1.2.1,<1.2.2 || >1.2.2,<1.3.0 || >1.3.0) requires botocore (>=1.15.32,<1.15.33).
  And because aiobotocore (1.0.7) depends on botocore (>=1.15.32,<1.15.33)
   and aiobotocore (1.1.0) depends on botocore (>=1.17.44,<1.17.45), aiobotocore (>=1.0.1,<1.1.1 || >1.1.1,<1.1.2 || >1.1.2,<1.2.0 || >1.2.0,<1.2.1 || >1.2.1,<1.2.2 || >1.2.2,<1.3.0 || >1.3.0) requires botocore (>=1.15.32,<1.15.33 || >=1.17.44,<1.17.45).
  And because aiobotocore (1.1.1) depends on botocore (>=1.17.44,<1.17.45)
   and aiobotocore (1.1.2) depends on botocore (>=1.17.44,<1.17.45), aiobotocore (>=1.0.1,<1.2.0 || >1.2.0,<1.2.1 || >1.2.1,<1.2.2 || >1.2.2,<1.3.0 || >1.3.0) requires botocore (>=1.15.32,<1.15.33 || >=1.17.44,<1.17.45).
  And because aiobotocore (1.2.0) depends on botocore (>=1.19.52,<1.19.53)
   and aiobotocore (1.2.1) depends on botocore (>=1.19.52,<1.19.53), aiobotocore (>=1.0.1,<1.2.2 || >1.2.2,<1.3.0 || >1.3.0) requires botocore (>=1.15.32,<1.15.33 || >=1.17.44,<1.17.45 || >=1.19.52,<1.19.53).
  And because aiobotocore (1.2.2) depends on botocore (>=1.19.52,<1.19.53)
   and aiobotocore (1.3.0) depends on botocore (>=1.20.49,<1.20.50), aiobotocore (>=1.0.1) requires botocore (>=1.15.32,<1.15.33 || >=1.17.44,<1.17.45 || >=1.19.52,<1.19.53 || >=1.20.49,<1.20.50).
  Because no versions of s3fs match >2021.4.0,<2022.0.0
   and s3fs (2021.4.0) depends on aiobotocore (>=1.0.1), s3fs (>=2021.4.0,<2022.0.0) requires aiobotocore (>=1.0.1).
  Thus, s3fs (>=2021.4.0,<2022.0.0) requires botocore (>=1.15.32,<1.15.33 || >=1.17.44,<1.17.45 || >=1.19.52,<1.19.53 || >=1.20.49,<1.20.50).
  And because boto3 (1.17.69) depends on botocore (>=1.20.69,<1.21.0)
   and no versions of boto3 match >1.17.69,<2.0.0, s3fs (>=2021.4.0,<2022.0.0) is incompatible with boto3 (>=1.17.69,<2.0.0).
  So, because src depends on both boto3 (^1.17.69) and s3fs (^2021.4.0), version solving failed. 
...

エラーの内容を確認する

上記例のエラーの内容を確認してみます

エラーのここの部分で、s3fs は botocore のバージョンに関して満たすべき条件が記載されています

Thus, s3fs (>=2021.4.0,<2022.0.0) requires botocore (>=1.15.32,<1.15.33 || >=1.17.44,<1.17.45 || >=1.19.52,<1.19.53 || >=1.20.49,<1.20.50).

1.20 系に関しては 1.20.49 以上 1.20.50 未満のバージョンにしか対応していないという風に読み取れます

一方 boto3 インストール時に入った botocore1.20.69 なので、この条件を満たしていません

これがエラーの原因となっている事がわかります

エラーを解決する

エラーを解決するには、botocore のバージョン >=2021.4.0,<2022.0.0) requires botocore (>=1.15.32,<1.15.33 || >=1.17.44,<1.17.45 || >=1.19.52,<1.19.53 || >=1.20.49,<1.20.50). に対応する boto3 のバージョンを探してきて入れれば良いという事になります

これを手動で探すのは非常に大変ですが、上手く poetry に探してもらうようにする事ができます

1. 制約の厳しい方を先に入れる

制約の厳しい方のライブラリを先に入れる事で、後から入れる方はすでに入っているライブラリのバージョンを加味して入れるように poetry に指示する事が可能です

この例では先に s3fs を入れます

$ poetry add s3fs
Using version ^2021.4.0 for s3fs

Updating dependencies
Resolving dependencies... (0.8s)

Writing lock file

Package operations: 14 installs, 0 updates, 0 removals

  • Installing idna (3.1)
  • Installing multidict (5.1.0)
  • Installing async-timeout (3.0.1)
  • Installing chardet (4.0.0)
  • Installing jmespath (0.10.0)
  • Installing typing-extensions (3.10.0.0)
  • Installing urllib3 (1.26.4)
  • Installing yarl (1.6.3)
  • Installing aiohttp (3.7.4.post0)
  • Installing aioitertools (0.7.1)
  • Installing botocore (1.20.49)
  • Installing wrapt (1.12.1)
  • Installing aiobotocore (1.3.0)
  • Installing s3fs (2021.4.0)

ちなみにこれで botocore 1.20.49 が入っている事がわかります

2. 制約の緩い方を入れる

次に制約の緩い方を入れるのですが、ここで poetry のコマンドを多少工夫する事で、すでに入っているライブラリの中で一番バージョンが新しいものを探してくるように指示する事ができます

具体的には以下の書式になります

poetry add "package-name<version-name"

例えば boto3 の例だと以下のようになります

$ poetry add "boto3<1.17.69"

Updating dependencies
Resolving dependencies... (1.6s)

Writing lock file

Package operations: 2 installs, 0 updates, 0 removals

  • Installing s3transfer (0.3.7)
  • Installing boto3 (1.17.49)

1.17.69 以下のバージョンで botocore 1.20.49 と競合しない 1.17.49 が入りました

このコマンドを走らせる前に boto3 の最新バージョンが知りたいというような場合は、 search コマンドを使う事で調べる事も可能です

$ poetry search boto3

boto3 (1.17.69)
 The AWS SDK for Python

まとめ

poetry でバージョンの競合によるエラーが発生した場合の対処法を記載しました