Pythonの依存関係管理:どのツールを選ぶべきですか?

Python dependency management which tool should you choose?

Poetry、Pip、およびCondaの詳細な比較

Image by Author

オリジナルの記事は2023年6月13日にhttps://mathdatasimplified.comで公開されました。

動機

データサイエンスプロジェクトが拡大するにつれて、依存関係の数も増えてきます。プロジェクトの環境を再現可能でメンテナブルに保つために、効率的な依存関係管理ツールを使用することが重要です。

したがって、依存関係管理のための3つの人気ツール、Pip、Conda、Poetryを比較することにしました。慎重な評価の結果、Poetryが効果的でパフォーマンスに優れていると結論づけられました。

この記事では、Poetryの利点について詳しく説明し、PipやCondaとの主な違いを強調します。

利用可能なパッケージ

多数のパッケージがあると、開発者が特定のパッケージやバージョンを見つけやすくなります。

Conda

「snscrape」などの一部のパッケージはcondaでインストールできません。また、Pandas 2.0などの特定のバージョンがCondaを介してインストールできない場合があります。

conda仮想環境内でpipを使用してパッケージの制限に対処することはできますが、pipでインストールされた依存関係をcondaが追跡できないため、依存関係の管理が困難になります。

$ conda list# packages in environment at /Users/khuyentran/miniconda3/envs/test-conda:## Name                    Version                   Build  Channel$ conda list # packages in environment at /Users/khuyentran/miniconda3/envs/test-conda: # # Name Version Build Channel

Pip

Pipは、Python Package Index(PyPI)および他のリポジトリから任意のパッケージをインストールできます。

Poetry

PoetryもPython Package Index(PyPI)および他のリポジトリからパッケージをインストールできます。

依存関係の数

環境内の依存関係の数を減らすことで、開発プロセスがシンプルになります。

Conda

Condaは完全な環境の分離を提供し、Pythonパッケージとシステムレベルの依存関係の両方を管理します。これにより、他のパッケージマネージャーに比べてパッケージサイズが大きくなる可能性があり、インストールおよび配布中により多くのストレージスペースを消費する可能性があります。

$ conda install pandas$ conda list          # packages in environment at /Users/khuyentran/miniconda3/envs/test-conda:## Name              Version         Build           Channel             blas                1.0             openblas                          bottleneck          1.3.5           py311ha0d4635_0                    bzip2               1.0.8           h620ffc9_4                        ca-certificates     2023.05.30      hca03da5_0                        libcxx              14.0.6          h848a8c0_0                        libffi              3.4.4           hca03da5_0                        libgfortran         5.0.0           11_3_0_hca03da5_28                 libgfortran5        11.3.0          h009349e_28                       libopenblas         0.3.21          h269037a_0                        llvm-openmp         14.0.6          hc6e5704_0                        ncurses             6.4             h313beb8_0                        numexpr             2.8.4           py311h6dc990b_1                    numpy               1.24.3          py311hb57d4eb_0                    numpy-base          1.24.3          py311h1d85a46_0                    openssl             3.0.8           h1a28f6b_0                        pandas              1.5.3           py311h6956b77_0                    pip                 23.0.1          py311hca03da5_0                    python              3.11.3          hb885b13_1                        python-dateutil     2.8.2           pyhd3eb1b0_0                      pytz                2022.7          py311hca03da5_0                    readline            8.2             h1a28f6b_0                        setuptools          67.8.0          py311hca03da5_0                    six                 1.16.0          pyhd3eb1b0_1                      sqlite              3.41.2          h80987f9_0                        tk                  8.6.12          hb8d0fd4_0                        tzdata              2023c           h04d1e81_0                        wheel               0.38.4          py311hca03da5_0                    xz                  5.4.2           h80987f9_0                        zlib                1.2.13          h5a0b063_0      

Pip

Pipはパッケージに必要な依存関係のみをインストールします。

$ pip install pandas$ pip listPackage         Version--------------- -------numpy           1.24.3pandas          2.0.2pip             22.3.1python-dateutil 2.8.2pytz            2023.3setuptools      65.5.0six             1.16.0tzdata          2023.3

Poetry

Poetryはパッケージに必要な依存関係のみをインストールします。

$ poetry add pandas$ poetry shownumpy           1.24.3 Pythonでの配列計算の基盤的なパッケージpandas          2.0.2  データ解析のための強力なデータ構造、時間...python-dateutil 2.8.2  Python標準のdatetimeモジュールの拡張pytz            2023.3 現代および歴史的な世界のタイムゾーン定義six             1.16.0 Python 2と3の互換性ツールtzdata          2023.3 IANAタイムゾーンデータの提供者

パッケージのアンインストール

パッケージとその依存関係をアンインストールすることで、ディスクスペースを解放し、不要なクラッターを防止し、ストレージリソースの使用を最適化できます。

Pip

Pipは指定されたパッケージのみを削除しますが、その依存関係は削除されません。これにより、未使用の依存関係が増え、ストレージスペースの使用量が増加し、競合が発生する可能性があります。

$ pip install pandas$ pip uninstall pandas$ pip listPackage         Version--------------- -------numpy           1.24.3pip             22.0.4python-dateutil 2.8.2pytz            2023.3setuptools      56.0.0six             1.16.0tzdata          2023.3

Conda

Condaはパッケージとその依存関係を削除します。

$ conda install -c conda pandas$ conda uninstall -c conda pandasCollecting package metadata (repodata.json): doneSolving environment: done## Package Plan ##  environment location: /Users/khuyentran/miniconda3/envs/test-conda  removed specs:    - pandasThe following packages will be REMOVED:  blas-1.0-openblas  bottleneck-1.3.5-py311ha0d4635_0  libcxx-14.0.6-h848a8c0_0  libgfortran-5.0.0-11_3_0_hca03da5_28  libgfortran5-11.3.0-h009349e_28  libopenblas-0.3.21-h269037a_0  llvm-openmp-14.0.6-hc6e5704_0  numexpr-2.8.4-py311h6dc990b_1  numpy-1.24.3-py311hb57d4eb_0  numpy-base-1.24.3-py311h1d85a46_0  pandas-1.5.3-py311h6956b77_0  python-dateutil-2.8.2-pyhd3eb1b0_0  pytz-2022.7-py311hca03da5_0  six-1.16.0-pyhd3eb1b0_1Proceed ([y]/n)? Preparing transaction: doneVerifying transaction: doneExecuting transaction: donePoetry

Poetry

Poetryもパッケージとその依存関係を削除します。

$ poetry add pandas$ poetry remove pandas  • Removing numpy (1.24.3)  • Removing pandas (2.0.2)  • Removing python-dateutil (2.8.2)  • Removing pytz (2023.3)  • Removing six (1.16.0)  • Removing tzdata (2023.3)

依存関係ファイル

依存関係ファイルは、必要なパッケージの正確なバージョンまたはバージョン範囲を指定することで、ソフトウェアプロジェクトの環境の再現性を確保します。

これにより、異なるシステムまたは異なる時点で同じ環境を再現し、同じ依存関係を持つ開発者間の協力を保証できます。

Conda

Conda環境で依存関係を保存するには、手動でファイルに書き込む必要があります。 environment.ymlファイルで指定されたバージョン範囲により、異なるバージョンがインストールされる可能性があり、環境を再現する際に互換性の問題が発生することがあります。

例として、pandasバージョン1.5.3をインストールしたと仮定します。 これは、依存関係を指定する例のenvironment.ymlファイルです:

# environment.ymlname: test-condachannels:  - defaultsdependencies:  - python=3.8  - pandas>=1.5

最新バージョンのpandasが2.0の場合、新しいユーザーが環境を再現しようとすると、pandas 2.0がインストールされます。

# 仮想環境を作成してアクティブ化する$ conda env create -n env$ conda activate env# 現在の環境のパッケージをリスト表示する$ conda list...pandas                   2.0

コードベースがpandasバージョン1.5.3に固有の構文または動作に依存しており、構文がバージョン2.0で変更されている場合、pandas 2.0でコードを実行するとバグが発生する可能性があります。

Pip

同じ問題がpipでも発生する可能性があります。

# requirements.txt pandas>=1.5

# 仮想環境を作成してアクティブ化する$ python3 -m venv venv$ source venv/bin/activate# 依存関係をインストールする$ pip install -r requirements.txt# パッケージをリスト表示する$ pip listPackage    Version---------- -------pandas       2.0

バージョンを固定するには、requirements.txtファイルにフリーズさせることができます:

$ pip freeze > requirements.txt

# requirements.txtnumpy==1.24.3pandas==1.5.3python-dateutil==2.8.2pytz==2023.3six==1.16.0

しかし、これによりコード環境が柔軟性を欠き、長期的にはメンテナンスが困難になる可能性があります。 依存関係に変更が加えられるたびに、手動でrequirements.txtファイルを変更する必要があり、時間がかかったりエラーを起こす可能性があります。

Poetry

Poetryは、パッケージをインストールするときにpyproject.tomlファイルを自動的に更新します。

次の例では、「pandas」パッケージがバージョン制約^1.5で追加されています。この柔軟なバージョン管理の方法により、手動での調整なしにプロジェクトを新しいリリースに適応できます。

$ poetry add 'pandas=^1.5'

# pyproject.toml[tool.poetry.dependencies]python = "^3.8"pandas = "^1.5"

poetry.lockファイルには、各パッケージとその依存関係の正確なバージョン番号が格納されます。

# poetry.lock...[[package]]name = "pandas"version = "1.5.3"description = "Powerful data structures for data analysis, time series, and statistics"category = "main"optional = falsepython-versions = ">=3.8"[package.dependencies]numpy = [    {version = ">=1.20.3", markers = "python_version < \"3.10\""},    {version = ">=1.21.0", markers = "python_version >= \"3.10\""},    {version = ">=1.23.2", markers = "python_version >= \"3.11\""},]python-dateutil = ">=2.8.2"pytz = ">=2020.1"tzdata = ">=2022.1"...

これにより、pyproject.tomlファイルでバージョン範囲が指定されている場合でも、インストールされるパッケージの一貫性が保証されます。ここでは、pandas 1.5.3がインストールされていることがわかります。

$ poetry install$ poetry show pandasname         : pandas                                                                  version      : 1.5.3                                                                   description  : Powerful data structures for data analysis, time series, and statistics dependencies - numpy >=1.20.3 - numpy >=1.21.0 - numpy >=1.23.2 - python-dateutil >=2.8.1 - pytz >=2020.1

開発と本番用の依存関係を分離する

依存関係を分離することで、開発目的(テストフレームワークやコード品質ツールなど)に必要なパッケージと、本番環境に必要なコア依存関係とを明確に区別できます。

Conda

Condaは本来別々の環境に対応していないため、開発環境と本番環境の2つの環境ファイルを作成する回避策があります。開発ファイルには、本番依存関係と開発依存関係の両方が含まれます。

# environment.ymlname: test-condachannels:  - defaultsdependencies:  # 本番パッケージ  - numpy  - pandas

# environment-dev.ymlname: test-conda-devchannels:  - defaultsdependencies:  # 本番パッケージ  - numpy  - pandas  # 開発パッケージ  - pytest  - pre-commit

Pip

Pipも別々の依存関係を直接サポートしていませんが、別々の要件ファイルを使用した同様のアプローチが使用できます。

# requirements.txtnumpy pandas

# requirements-dev.txt-r requirements.txtpytestpre-commit

# 本番のみをインストール$ pip install -r requirements.txt# 開発と本番の両方をインストール$ pip install -r requirements-dev.txt

Poetry

Poetryは、1つのファイル内でグループをサポートすることで依存関係の管理を簡素化します。これにより、すべての依存関係を1か所に集めることができます。

$ poetry add numpy pandas$ poetry add --group dev pytest pre-commit

# pyproject.toml[tool.poetry.dependencies]python = "^3.8"pandas = "^2.0"numpy = "^1.24.3"[tool.poetry.group.dev.dependencies]pytest = "^7.3.2"pre-commit = "^3.3.2"

本番の依存関係のみをインストールするには:

$ poetry install --only main

開発と本番の両方の依存関係をインストールするには:

$ poetry install

環境の更新

依存関係の更新は、バグ修正、パフォーマンスの改善、および新しいパッケージバージョンで導入された新機能の利点を得るために重要です。

Conda

Condaを使用すると、指定されたパッケージのみを更新できます。

$ conda install -c conda pandas$ conda install -c anaconda scikit-learn

# 新しいバージョンが利用可能です$ conda update pandas$ conda update scikit-learn

その後、更新された依存関係と同期させるために、environment.yamlファイルを手動で更新する必要があります。

$ conda env export > environment.yml

Pip

Pipも指定されたパッケージのみを更新でき、要件.txtファイルを手動で更新する必要があります。

$ pip install -U pandas

$ pip freeze > requirements.txt

Poetry

Poetryを使用すると、pyproject.tomlファイルで指定されたすべてのパッケージをアップグレードするためにupdateコマンドを使用できます。この操作により、パッケージの仕様とロックファイルの間の一貫性が確保されるように、poetry.lockファイルが自動的に更新されます。

$ poetry add pandas scikit-learn# 新しいバージョンが利用可能ですpoetry update依存関係を更新中... (0.3s)ロックファイルを書き込み中: パッケージ操作: 0個のインストール、2個の更新、0個の削除  • pandasを更新中 (2.0.0 -> 2.0.2)  • scikit-learnを更新中 (1.2.0 -> 1.2.2)

依存関係の解決

プロジェクトで必要なパッケージやライブラリに矛盾するバージョンや非互換な依存関係がある場合、依存関係の解決はエラーや実行時の問題、プロジェクトの失敗を回避するために重要です。

Pip

pipはパッケージを順次インストールするため、指定された順序に従って1つずつパッケージをインストールします。この順次アプローチは、パッケージに非互換な依存関係やバージョン要件がある場合に、時には依存関係の競合を引き起こすことがあります。

たとえば、最初にpandas==2.0.2をインストールして、numpy>=1.20.3を必要とする場合を考えてみましょう。その後、pipを使用してnumpy==1.20.2をインストールします。パッケージの競合が発生しますが、pipはnumpyのバージョンを更新し続けます。

$ pip install pandas==2.0.2$ pip install numpy==1.22.2Collecting numpy=1.20.2  Attempting uninstall: numpy    Found existing installation: numpy 1.24.3    Uninstalling numpy-1.24.3:      Successfully uninstalled numpy-1.24.3ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.pandas 2.0.2 requires numpy>=1.20.3; python_version < "3.10", but you have numpy 1.20.2 which is incompatible.Successfully installed numpy-1.20.2

Conda

Condaは、パッケージのバージョンと依存関係のすべての組み合わせを探索して、互換性のあるセットを見つけるためにSATソルバを使用します。

たとえば、既存のパッケージが依存関係に特定の制約を持っている場合(例えば、statsmodels==0.13.2はnumpy>=1.21.2,<2.0a0を必要とする)、そしてインストールしたいパッケージがその要件を満たさない場合(例えば、numpy<1.21.2)、condaはすぐにエラーを発生させません。その代わりに、必要なすべてのパッケージとその依存関係の互換性のあるバージョンを熱心に検索して、適切な解が見つからない場合にのみエラーを報告します。

$ conda install 'statsmodels==0.13.2'$ conda search 'statsmodels==0.13.2' --infodependencies:   - numpy >=1.21.2,<2.0a0  - packaging >=21.3  - pandas >=1.0  - patsy >=0.5.2  - python >=3.9,<3.10.0a0  - scipy >=1.3$ conda install 'numpy<1.21.2'...Package ca-certificates conflicts for:python=3.8 -> openssl[version='>=1.1.1t,<1.1.2a'] -> ca-certificatesopenssl -> ca-certificatesca-certificatescryptography -> openssl[version='>1.1.0,<3.1.0'] -> ca-certificatesPackage idna conflicts for:requests -> urllib3[version='>=1.21.1,<1.27'] -> idna[version='>=2.0.0']requests -> idna[version='>=2.5,<3|>=2.5,<4']idnapooch -> requests -> idna[version='>=2.5,<3|>=2.5,<4']urllib3 -> idna[version='>=2.0.0']Package numexpr conflicts for:statsmodels==0.13.2 -> pandas[version='>=1.0'] -> numexpr[version='>=2.7.0|>=2.7.1|>=2.7.3']numexprpandas==1.5.3 -> numexpr[version='>=2.7.3']Package patsy conflicts for:statsmodels==0.13.2 -> patsy[version='>=0.5.2']patsyPackage chardet conflicts for:requests -> chardet[version='>=3.0.2,<4|>=3.0.2,<5']pooch -> requests -> chardet[version='>=3.0.2,<4|>=3.0.2,<5']Package python-dateutil conflicts for:statsmodels==0.13.2 -> pandas[version='>=1.0'] -> python-dateutil[version='>=2.7.3|>=2.8.1']python-dateutilpandas==1.5.3 -> python-dateutil[version='>=2.8.1']Package setuptools conflicts for:numexpr -> setuptoolspip -> setuptoolswheel -> setuptoolssetuptoolspython=3.8 -> pip -> setuptoolspandas==1.5.3 -> numexpr[version='>=2.7.3'] -> setuptoolsPackage brotlipy conflicts for:urllib3 -> brotlipy[version='>=0.6.0']brotlipyrequests -> urllib3[version='>=1.21.1,<1.27'] -> brotlipy[version='>=0.6.0']Package pytz conflicts for:pytzpandas==1.5.3 -> pytz[version='>=2020.1']statsmodels==0.13.2 -> pandas[version='>=1.0'] -> pytz[version='>=2017.3|>=2020.1']

このアプローチは、解決策を見つける可能性を高めますが、特に広範な環境を扱う場合には計算量が大きくなることがあります。

Poetry

プロジェクトの直接の依存関係に焦点を当てることにより、Poetryの決定論的リゾルバーは検索スペースを狭め、解決プロセスをより効率的にします。指定された制約、バージョン範囲、または特定のバージョンなどを評価し、すぐに競合があるかどうかを特定します。

$ poetry add 'seaborn==0.12.2'$ poetry add 'matplotlib<3.1' Because poetry shell depends on seaborn (0.12.2) which depends on matplotlib (>=3.1,<3.6.1 || >3.6.1), matplotlib is required.So, because poetry shell depends on matplotlib (<3.1), version solving failed.

この即時フィードバックにより、潜在的な問題のエスカレーションを防ぎ、開発プロセスの早い段階で問題に対処できます。たとえば、以下のコードでは、seabornの要件を緩和して、特定のバージョンのmatplotlibをインストールできるようにできます。

poetry add 'seaborn<=0.12.2'  'matplotlib<3.1' Package operations: 1 install, 2 updates, 4 removals  • Removing contourpy (1.0.7)  • Removing fonttools (4.40.0)  • Removing packaging (23.1)  • Removing pillow (9.5.0)  • Updating matplotlib (3.7.1 -> 3.0.3)  • Installing scipy (1.9.3)  • Updating seaborn (0.12.2 -> 0.11.2)

結論

要約すると、Poetryはpipやcondaよりもいくつかの利点を提供します。

  1. 広範なパッケージ選択: Poetryは、プロジェクトに多様なエコシステムを活用するためにPyPIで利用可能な幅広い範囲のパッケージにアクセスできます。
  2. 効率的な依存関係管理: Poetryは指定されたパッケージに必要な依存関係のみをインストールし、環境内の不要なパッケージの数を減らします。
  3. 簡略化されたパッケージの削除: Poetryは、パッケージとそれに関連する依存関係の削除を簡素化し、クリーンで効率的なプロジェクト環境を維持することが容易になります。
  4. 依存関係の解決: Poetryの決定論的リゾルバーは、依存関係を効率的に解決し、不整合や競合を迅速に特定して解決します。

Poetryは、チームメイトが学習して適応するために追加の時間と労力が必要かもしれませんが、Poetryのようなツールを使用することで、長期的に時間と労力を節約できます。

私はデータサイエンスのコンセプトについて書くことや、さまざまなデータサイエンスのツールで遊ぶことが大好きです。最新の投稿については、以下の方法で更新情報を受け取ることができます。

  • Data Science Simplifiedのニュースレターに登録する
  • LinkedInとTwitterで私につながる

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more