pipでインストールされたPythonパッケージの依存関係の特定


151

ピップフリーズを実行すると、明示的にインストールしなかった多数のPythonパッケージが表示されます。

$ pip freeze
Cheetah==2.4.3
GnuPGInterface==0.3.2
Landscape-Client==11.01
M2Crypto==0.20.1
PAM==0.4.2
PIL==1.1.7
PyYAML==3.09
Twisted-Core==10.2.0
Twisted-Web==10.2.0
(etc.)

pipがこれらの特定の依存パッケージをインストールした理由を確認する方法はありますか?言い換えると、これらのパッケージを依存関係として持っている親パッケージをどのように判断しますか?

たとえば、Twistedを使用したい場合や、誤ってパッケージをアンインストールしたりアップグレードしたりしないことを理解するまで、パッケージに依存したくありません。

回答:


180

依存関係をツリー構造として表示するpipdeptreeを試すことができます。例:

$ pipdeptree
Lookupy==0.1
wsgiref==0.1.2
argparse==1.2.1
psycopg2==2.5.2
Flask-Script==0.6.6
  - Flask [installed: 0.10.1]
    - Werkzeug [required: >=0.7, installed: 0.9.4]
    - Jinja2 [required: >=2.4, installed: 2.7.2]
      - MarkupSafe [installed: 0.18]
    - itsdangerous [required: >=0.21, installed: 0.23]
alembic==0.6.2
  - SQLAlchemy [required: >=0.7.3, installed: 0.9.1]
  - Mako [installed: 0.9.1]
    - MarkupSafe [required: >=0.9.2, installed: 0.18]
ipython==2.0.0
slugify==0.0.1
redis==2.9.1

それを実行するには:

pip install pipdeptree


編集:コメントの@Estebanで述べられているように、実行されているインストール済みのWerkzeugを見つけるために-r、単一のパッケージを-p <package_name>使用してツリーを逆にリストすることもできます:

$ pipdeptree -r -p Werkzeug
Werkzeug==0.11.15
  - Flask==0.12 [requires: Werkzeug>=0.7]

6
私は、実行する必要がある@markの質問に完全に答えると信じています:pipdeptree -r 「依存関係ツリーを逆の方法で示します。
エステバン2016

ローカルにインストールされたパッケージだけでなく、すべてのPyPiパッケージの逆ツリーをどのように表示できますか?
Tijme 2017

2
pipdeptree素晴らしいです。残念ながら、それはcondaによってインストールされたパッケージの依存関係を考慮していないようです:たとえば、pipを使用してインストールされ、conda を使用してインストールされたconda envの場合matplotlib、依存関係がないと依存関係がないとしてpipdeptreeに表示されます(また、要件)。numpyscipyscipypip show scipy
djvg 2018

@Dennis私は試していませんが、これはconda github.com/rvalieris/conda-treeで
djsutho

1
これを仮想環境で使用するには、python -m pipdeptreeそれ以外の場合(実行可能ファイルがvirtualenvにインストールされている場合でも)、システムの依存関係のみをリストする必要があります。
Zim

81

pip showコマンドは、パッケージが指定されたパッケージ(指定したパッケージが既にインストールされている必要があります)に必要とされるものを表示します:

$ pip show specloud

Package: specloud
Version: 0.4.4
Requires:
nose
figleaf
pinocchio

pip show pipバージョン1.4rc5で導入されました


1
pip showバージョン1.4rc5で導入され、(執筆時点で)1.4.1
drevicko 2013年

10
親の代わりに特定のパッケージの子(依存関係)が表示されるため、これは私の質問に正確には答えません。しかし、このコマンドを使用して、各パッケージの依存関係をチェックするために何かを一緒に投げるのは簡単です。したがって、たとえば、PyYAMLが必要なインストール済みパッケージを特定できます。
Mark Chackerian、2014

4
以前のコメントのとおり、このシェルコマンドは、インストールされている各パッケージのすべての依存関係をダンプします。grep -v "\ -e" | sed s /\=\=.*// | awk 'system( "pip show" $ 1)'
Mark Chackerian

以前のコメントからのスクリプトの更新バージョンはpip freeze | grep -v "\-e" | sed s/\=\=.*// | awk 'system("pip show " $1)' | grep -E '^(Name:|Requires:)' | sed s/Name:/\\\nName:/ -ですが、pipdeptreeがより良い解決策になっているようです。
Mark Chackerian 2017

14

最近hnスレッドで言ったように、私は以下をお勧めします:

requirements.txt主な依存関係がコメント化されたファイルがあります。

## this is needed for whatever reason
package1

依存関係をインストールしますpip install -r requirements.txt。これで、依存関係の完全なリストが表示されますpip freeze -r requirements.txt

## this is needed for whatever reason
package1==1.2.3

## The following requirements were added by pip --freeze:
package1-dependency1==1.2.3
package1-dependency1==1.2.3

これにより、ファイル構造をコメント付きで保持し、依存関係と依存関係をうまく分離できます。このようにして、そのうちの1つを削除する必要がある日に、より良い時間を過ごすことができます:)

次の点に注意してください。

  • あなたはrequirements.rawあなたの完全を再構築するためにバージョン管理できれいにすることができますrequirements.txt
  • プロセスでgit urlが卵名に置き換えられることに注意してください。
  • 依存関係の依存関係は依然としてアルファベット順にソートされているため、どのパッケージがどのパッケージを必要としているかは直接はわかりませんが、現時点では実際には必要ありません。
  • pip install --no-install <package_name>特定の要件をリストするために使用します。
  • 使用しない場合は、virtualenvを使用してください。

1
なぜこれpip freeze -r requirements.txtが広く使われていないのか理解できません。依存関係とサブ依存関係の維持に非常に役立ちます。
Penkey Suresh 2017

1
マイナーな注意:pip installはサポートされなくなりました--no-install
ライアン

7

また、要件のパッケージをパイプでパイプライン表示する1行のコマンドを使用することもできます。

cut -d'=' -f1 requirements.txt | xargs pip show

1
requirements.txtの形式はより複雑なので、通常はできません<package_name>==<package_version>
Piotr Dobrogost 16年

3

まず、pip freeze現在インストールされているすべてのパッケージPythonを表示します。必ずしもPIPを使用しているわけではありません。

次に、Pythonパッケージには、依存パッケージと必要なバージョンに関する情報が含まれていますここで説明する方法を使用して、特定のpkgの依存関係を確認できます。パッケージをアップグレードする場合、PIPのようなインストーラースクリプトが依存関係のアップグレードを処理します。

パッケージの更新を解決するには、PIP要件ファイルの使用をお勧めします。必要なパッケージとバージョンを定義し、pip installを使用してそれらを一度にインストールできます。


3

pipupgradeを使用してください!

$ pip install pipupgrade
$ pipupgrade --format tree --all --check

pipupgradeは、依存関係グラフを表示し、可能なパッケージ(セマンティックバージョニングに基づく)の各パッケージを強調表示します。また、競合する子の依存関係をきれいに表示します。pipupgradeまた、複数のPython環境内に存在するパッケージを確実にアップグレードします。Python2.7 +、Python3.4 +およびpip9 +、pip10 +、pip18 +、pip19 +と互換性があります。

ここに画像の説明を入力してください


1

(回避策、本当の答えではありません)

lxmlがインストールされておらず、誰がlxmlを必要としているかを知りたいという同じ問題がありました。 lxmlが必要なのは誰か。最終的に問題を回避することになった。

  1. 私のサイトパッケージがどこに置かれていたかを記録しました。

  2. そこに行き、インポート用に再帰的なgrepを実行します(最後のgrepの--invert-matchは、lxml自体のファイルを考慮から外すのに役立ちます)。

はい、pipを使用してそれを行う方法についての答えではありませんが、何らかの理由で、ここでの提案は成功しませんでした。

 site-packages me$ egrep -i --include=*.py  -r -n lxml . | grep import | grep --invert-match /lxml/

1

この問題を解決する簡単なスクリプトを書きました。次のスクリプトは、特定のパッケージの親(依存)パッケージを表示します。これにより、特定のパッケージをアップグレードまたはインストールしても安全であることを確認できます。次のように使用できます。dependants.py PACKAGENAME

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""Find dependants of a Python package"""

import logging
import pip
import pkg_resources
import sys

__program__ = 'dependants.py'


def get_dependants(target_name):
    for package in pip._internal.utils.misc.get_installed_distributions():
        for requirement_package in package.requires():
            requirement_name = requirement_package.project_name
            if requirement_name == target_name:
                yield package.project_name


# configure logging
logging.basicConfig(format='%(levelname)s: %(message)s',
                    level=logging.INFO)

try:
    target_name = sys.argv[1]
except IndexError:
    logging.error('missing package name')
    sys.exit(1)

try:
    pkg_resources.get_distribution(target_name)
except pkg_resources.DistributionNotFound:
    logging.error("'%s' is not a valid package", target_name)
    sys.exit(1)

print(list(get_dependants(target_name)))

get_installed_distributions()メソッドが使用できなくなったため、これは機能しなくなりました。github.com/pypa/pip/issues/5243
Phil Gyford
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.