显示包依赖树的命令行工具。
项目描述
pipdeptree
pipdeptree
是一个命令行工具,用于以依赖树的形式显示已安装的 Python 包。它适用于安装在机器上的全局包以及虚拟环境中的包。由于 pip freeze
将所有依赖项显示为平面列表,因此需要一些努力才能找出哪些是顶级包以及它们依赖于哪些包。解决可能因为较旧版本的 pip
没有真正解决依赖问题而安装的冲突依赖项也很繁琐[^1]。 pipdeptree
可以通过识别环境中安装的冲突依赖项来帮助解决这个问题。
在某种程度上,pipdeptree
受到 Leiningen 的 lein deps :tree
命令的启发。
安装
pip install pipdeptree
在虚拟环境中运行
新特性 2.0.0 版本
如果您想在特定虚拟环境中运行 pipdeptree,可以指定 --python
选项。请注意,此功能最近在版本 2.0.0
中添加。
或者,您还可以在虚拟环境中安装 pipdeptree,然后从那里运行它。
截至版本 2.21.0
,您还可以传递 --python auto
,其中它将尝试检测您的虚拟环境并从中获取解释器。如果无法检测到,则会失败。
使用方法和示例
为了给您一个简要的概念,以下是 pipdeptree
与 pip freeze
的输出比较
$ pip freeze
Flask==0.10.1
itsdangerous==0.24
Jinja2==2.11.2
-e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy
MarkupSafe==0.22
pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl
Werkzeug==0.11.2
现在看看 pipdeptree
的输出
$ pipdeptree
Warning!!! Possibly conflicting dependencies found:
* Jinja2==2.11.2
- MarkupSafe [required: >=0.23, installed: 0.22]
------------------------------------------------------------------------
Flask==0.10.1
- itsdangerous [required: >=0.21, installed: 0.24]
- Jinja2 [required: >=2.4, installed: 2.11.2]
- MarkupSafe [required: >=0.23, installed: 0.22]
- Werkzeug [required: >=0.7, installed: 0.11.2]
Lookupy==0.1
pipdeptree==2.0.0b1
- pip [required: >=6.0.0, installed: 20.1.1]
setuptools==47.1.1
wheel==0.34.2
是否可以找出为什么安装了特定的包?
新特性 0.5.0 版本
是的,为此有一个 --reverse
(或简单地 -r
)标志。要找出哪些包依赖于特定的包(或多个包),可以将它与 --packages
选项组合,如下所示
$ pipdeptree --reverse --packages itsdangerous,MarkupSafe
Warning!!! Possibly conflicting dependencies found:
* Jinja2==2.11.2
- MarkupSafe [required: >=0.23, installed: 0.22]
------------------------------------------------------------------------
itsdangerous==0.24
- Flask==0.10.1 [requires: itsdangerous>=0.21]
MarkupSafe==0.22
- Jinja2==2.11.2 [requires: MarkupSafe>=0.23]
- Flask==0.10.1 [requires: Jinja2>=2.4]
有关冲突依赖项警告的说明是什么?
如上输出所示,pipdeptree
默认会警告可能的冲突依赖项。任何被指定为多个具有不同版本的包的依赖项都视为冲突依赖项。如果曾经使用较旧版本的 pip(<=20.2)[^2] 安装依赖项,则可能会出现冲突依赖项。警告将打印到 stderr 而不是 stdout,可以通过指定 -w silence
或 --warn silence
选项完全禁用。另一方面,可以通过指定 --warn fail
使其更严格,在这种情况下,命令不仅会打印警告到 stderr,还会退出并返回非零状态码。这适用于您希望将其集成到 CI 管道中。
注意: --warn
选项是在版本 0.6.0
中添加的。如果您使用的是旧版本,请使用 --nowarn
标志来禁用警告。
关于循环依赖的警告
如果任何包具有循环依赖(例如,包 A 依赖于包 B,而包 B 依赖于包 A),则 pipdeptree
也会打印有关该问题的警告。
$ pipdeptree --exclude pip,pipdeptree,setuptools,wheel
Warning!!! Cyclic dependencies found:
- CircularDependencyA => CircularDependencyB => CircularDependencyA
- CircularDependencyB => CircularDependencyA => CircularDependencyB
------------------------------------------------------------------------
wsgiref==0.1.2
argparse==1.2.1
与有关冲突依赖项的警告类似,这些警告也会打印到 stderr,并可以使用 --warn
选项进行控制。
在上面的示例中,您还可以看到 --exclude
选项,它相当于 --packages
的对立面,即这些包将排除在输出之外。
使用 pipdeptree 编写 requirements.txt 文件
如果您希望仅在 requirements.txt
文件中跟踪顶级包,可以通过 grep 仅从输出中获取顶级行来做到这一点。
$ pipdeptree --warn silence | grep -E '^\w+'
Flask==0.10.1
gnureadline==8.0.0
Lookupy==0.1
pipdeptree==2.0.0b1
setuptools==47.1.1
wheel==0.34.2
尽管如此,这里存在问题——输出没有提及Lookupy
作为一个可编辑包已被安装(参考上面的pip freeze
输出)并且其源信息丢失。要解决这个问题,必须使用带有-f
或--freeze
标志的pipdeptree
。
$ pipdeptree -f --warn silence | grep -E '^[a-zA-Z0-9\-]+'
Flask==0.10.1
gnureadline==8.0.0
-e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy
pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl
setuptools==47.1.1
wheel==0.34.2
$ pipdeptree -f --warn silence | grep -E '^[a-zA-Z0-9\-]+' > requirements.txt
冻结标志不会在子依赖前加上连字符,因此可以将pipdeptree -f
的整个输出写入requirements.txt文件,使其既符合人类阅读习惯(由于缩进),也符合pip的要求。
$ pipdeptree -f | tee locked-requirements.txt
Flask==0.10.1
itsdangerous==0.24
Jinja2==2.11.2
MarkupSafe==0.23
Werkzeug==0.11.2
gnureadline==8.0.0
-e git+git@github.com:naiquevin/lookupy.git@cdbe30c160e1c29802df75e145ea4ad903c05386#egg=Lookupy
pipdeptree @ file:///private/tmp/pipdeptree-2.0.0b1-py3-none-any.whl
pip==20.1.1
setuptools==47.1.1
wheel==0.34.2
在确认没有冲突的依赖项后,甚至可以将此视为一个“锁定文件”,其中所有包,包括临时依赖项都将锁定到当前安装的版本。请注意,locked-requirements.txt
文件可能会出现重复条目。尽管pip install
不会对此提出异议,但您可以通过以下方式避免重复行(以牺牲缩进为代价),
$ pipdeptree -f | sed 's/ //g' | sort -u > locked-requirements.txt
使用pipdeptree与外部工具结合使用
新特性 0.5.0 版本
还可以让pipdeptree
输出依赖树结构的json表示,以便它可以作为其他外部工具的输入。
$ pipdeptree --json
请注意,--json
将输出所有包及其直接依赖项的扁平列表。这本身并不很有用。要获取嵌套的json,请使用--json-tree
新功能 0.11.0 版本
$ pipdeptree --json-tree
可视化依赖图
依赖图也可以使用GraphViz进行可视化。
$ pipdeptree --graph-output dot > dependencies.dot
$ pipdeptree --graph-output pdf > dependencies.pdf
$ pipdeptree --graph-output png > dependencies.png
$ pipdeptree --graph-output svg > dependencies.svg
请注意,graphviz
是一个可选依赖项,即只有在您想使用--graph-output
时才需要。如果环境中安装的graphviz
版本早于0.18.1,则会显示有关升级graphviz
的警告。将很快停止支持graphviz的旧版本。
从版本2.0.0b1
开始,支持所有输出格式(即文本、json、json-tree和graph)的--package
和--reverse
标志。
在早期版本中,--json
、--json-tree
和--graph-output
选项会覆盖--package
和--reverse
。
用法
% pipdeptree --help
usage: pipdeptree [-h] [-v] [-w [{silence,suppress,fail}]] [--python PYTHON] [-p P] [-e P] [-a] [-l | -u] [-f] [--encoding E] [-d D] [-r] [--license] [-j | --json-tree | --mermaid | --graph-output FMT]
Dependency tree of the installed python packages
options:
-h, --help show this help message and exit
-v, --version show program's version number and exit
-w [{silence,suppress,fail}], --warn [{silence,suppress,fail}]
warning control: suppress will show warnings but return 0 whether or not they are present; silence will not show warnings at all and always return 0; fail will show warnings and return 1 if any are present (default:
suppress)
select:
choose what to render
--python PYTHON Python interpreter to inspect (default: /usr/local/bin/python)
-p P, --packages P comma separated list of packages to show - wildcards are supported, like 'somepackage.*' (default: None)
-e P, --exclude P comma separated list of packages to not show - wildcards are supported, like 'somepackage.*'. (cannot combine with -p or -a) (default: None)
-a, --all list all deps at top level (default: False)
-l, --local-only if in a virtualenv that has global access do not show globally installed packages (default: False)
-u, --user-only only show installations in the user site dir (default: False)
render:
choose how to render the dependency tree (by default will use text mode)
-f, --freeze print names so as to write freeze files (default: False)
--encoding E the encoding to use when writing to the output (default: utf-8)
-d D, --depth D limit the depth of the tree (text render only) (default: inf)
-r, --reverse render the dependency tree in the reverse fashion ie. the sub-dependencies are listed with the list of packages that need them under them (default: False)
--license list the license(s) of a package (text render only) (default: False)
-j, --json raw JSON - this will yield output that may be used by external tools (default: False)
--json-tree nested JSON - mimics the text format layout (default: False)
--mermaid https://mermaid.npmjs.net.cn flow diagram (default: False)
--graph-output FMT Graphviz rendering with the value being the graphviz output e.g.: dot, jpeg, pdf, png, svg (default: None)
已知问题
pipdeptree
依赖于pip
的内部API。我完全理解这是一个坏主意,但它大多数时候都能正常工作!在罕见的情况下,当pip
的新版本发布时,如果内部API有向后不兼容的更改,它就会中断。因此,如果您在版本未固定的环境中使用此工具(尤其是自动化或CD/CI管道),请务必注意。
限制和替代方案
pipdeptree
仅查看当前环境中使用pip安装的包,构建树,然后以指定的格式输出。如果您想在不安装包的情况下生成依赖树,则需要依赖解析器。您可能想检查类似pipgrip或poetry的替代方案。
许可
MIT(请参阅LICENSE)
脚注
[^1]: pip版本20.3于2020年11月发布,包含依赖解析器https://blog.python.org/2020/11/pip-20-3-release-new-resolver.html_
[^2]: pip版本20.3于2020年11月发布,包含依赖解析器https://blog.python.org/2020/11/pip-20-3-release-new-resolver.html_
[^3]: 如果您在Windows(PowerShell)上,可以运行pipdeptree --warn silence | Select-String -Pattern '^\w+'
代替grep
项目详情
下载文件
下载适用于您平台文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。