基于 PubGrub 算法的具有深度树预览功能的轻量级 pip 依赖解析器
项目描述
pigrip
pipgrip是一个轻量级的 pip 依赖解析器,具有基于PubGrub 算法的深度树预览功能,诗歌也使用该算法。对于一个或多个PEP 508依赖项规范,pipgrip 递归地获取/构建版本求解所需的 Python 轮子,并可选地呈现完整的依赖关系树。
pipgrip 与诗歌
诗歌提供了依赖解析的包管理,基本上取代了 pip/setuptools。这意味着诗歌包不包含setup.py
,因此不兼容pip install -e
:诗歌项目必须转换为基于 setuptools 的项目,例如dephell。为了避免这样的麻烦,pipgrip 只需要选择的包 + 依赖项以通常的方式可用于 pip。
pipgrip 与 pipdeptree
对于离线使用,pipdeptree可以检查当前环境并显示当前安装的包之间的关系。然而,这需要安装包,并且(尽管有关于例如循环依赖的警告)不提供任何形式的依赖解析,因为它仅基于安装在环境中的(单个)包版本。使用 pipgrip 时可以避免这些缺点,因为不需要安装包,并且所有可用于 pip 的版本都已考虑在内。
安装
PyPI上提供了这个纯 Python、独立于操作系统的包:
pip install pipgrip
用法
该软件包可用于:
- 为任何给定的 pip 兼容包呈现详尽的依赖关系树:
pipgrip --tree requests
- 通过解析所需包的最新可行组合来缓解Python 依赖地狱
- 通过在 CI 管道中运行 pipgrip 作为阶段来避免错误
- 检测给定约束的版本冲突并提供人类可读的反馈
- 警告本地项目中的循环依赖项[并无论如何安装它们]:
pipgrip -v --tree . [--install -e]
- 无需担心安装复杂的软件包:
pipgrip --install aiobotocore[awscli]
- 为可重复安装生成具有完整工作依赖集的锁定文件:
pipgrip --lock aiobotocore[awscli] && pip install aiobotocore[awscli] --constraint ./pipgrip.lock
- 将多个包的依赖树组合成一组统一的固定包:
pipgrip .[boto3] s3transfer==0.2.1 s3fs smart_open[s3]
另请参阅已知的警告。
或者,可以使用空格/换行符分隔的要求填充环境变量PIPGRIP_ADDITIONAL_REQUIREMENTS
,这些要求将附加到通过 CLI 传递的要求中。
$ pipgrip --help
Usage: pipgrip [OPTIONS] [DEPENDENCIES]...
pipgrip is a lightweight pip dependency resolver with deptree preview
functionality based on the PubGrub algorithm, which is also used by poetry.
For one or more PEP 508 dependency specifications, pipgrip recursively
fetches/builds the Python wheels necessary for version solving, and optionally
renders the full resulting dependency tree.
Options:
--install Install full dependency tree after resolving.
-e, --editable Install a project in editable mode.
--user Install to the Python user install directory for
your platform -- typically ~/.local/, or
%APPDATA%\Python on Windows.
-r, --requirements-file FILE Install from the given requirements file. This
option can be used multiple times.
--lock Write out pins to './pipgrip.lock'.
--pipe Output space-separated pins instead of newline-
separated pins.
--json Output pins as JSON dict instead of newline-
separated pins. Combine with --tree for a detailed
nested JSON dependency tree.
--sort Sort pins alphabetically before writing out. Can
be used bare, or in combination with --lock,
--pipe, --json, --tree-json, or --tree-json-exact.
--tree Output human readable dependency tree (top-down).
Combine with --json for a detailed nested JSON
dependency tree. Use --tree-json instead for a
simplified JSON dependency tree (requirement
strings as keys, dependencies as values), or
--tree-json-exact for exact pins as keys.
--tree-ascii Output human readable dependency tree with ASCII
tree markers.
--reversed-tree Output human readable dependency tree (bottom-up).
--max-depth INTEGER Maximum (JSON) tree rendering depth (default -1).
--cache-dir DIRECTORY Use a custom cache dir.
--no-cache-dir Disable pip cache for the wheels downloaded by
pipper. Overrides --cache-dir.
--index-url TEXT Base URL of the Python Package Index (default
https://pypi.org/simple).
--extra-index-url TEXT Extra URLs of package indexes to use in addition
to --index-url.
--pre Include pre-release and development versions. By
default, pip implicitly excludes pre-releases
(unless specified otherwise by PEP 440).
-v, --verbose Control verbosity: -v will print cyclic
dependencies (WARNING), -vv will show solving
decisions (INFO), -vvv for development (DEBUG).
-h, --help Show this message and exit.
依赖树
详尽的依赖树,无需安装任何包(最多构建一些轮子)。
$ pipgrip --tree pipgrip
pipgrip (0.8.1)
├── anytree (2.8.0)
│ └── six>=1.9.0 (1.16.0)
├── click>=7 (8.1.3)
├── packaging>=17 (21.3)
│ └── pyparsing!=3.0.5,>=2.0.2 (3.0.9)
├── pip>=7.1.0 (22.1.1)
├── pkginfo<1.8,>=1.4.2 (1.7.1)
├── setuptools>=38.3 (62.3.2)
└── wheel (0.37.1)
有关更多详细信息/进一步处理,请结合--tree
使用以--json
获取详细的嵌套 JSON 依赖树。另见--tree-ascii
(无 unicode 树标记)和--tree-json
& --tree-json-exact
(简化的 JSON 依赖树)。
锁定文件生成
使用该--lock
选项,已解决(固定)的依赖项会另外写入./pipgrip.lock
.
$ pipgrip --tree --lock botocore==1.13.48 'boto3>=1.10,<1.10.50'
botocore==1.13.48 (1.13.48)
├── docutils<0.16,>=0.10 (0.15.2)
├── jmespath<1.0.0,>=0.7.1 (0.9.5)
├── python-dateutil<3.0.0,>=2.1 (2.8.1)
│ └── six>=1.5 (1.14.0)
└── urllib3<1.26,>=1.20 (1.25.8)
boto3<1.10.50,>=1.10 (1.10.48)
├── botocore<1.14.0,>=1.13.48 (1.13.48)
│ ├── docutils<0.16,>=0.10 (0.15.2)
│ ├── jmespath<1.0.0,>=0.7.1 (0.9.5)
│ ├── python-dateutil<3.0.0,>=2.1 (2.8.1)
│ │ └── six>=1.5 (1.14.0)
│ └── urllib3<1.26,>=1.20 (1.25.8)
├── jmespath<1.0.0,>=0.7.1 (0.9.5)
└── s3transfer<0.3.0,>=0.2.0 (0.2.1)
└── botocore<2.0.0,>=1.12.36 (1.13.48)
├── docutils<0.16,>=0.10 (0.15.2)
├── jmespath<1.0.0,>=0.7.1 (0.9.5)
├── python-dateutil<3.0.0,>=2.1 (2.8.1)
│ └── six>=1.5 (1.14.0)
└── urllib3<1.26,>=1.20 (1.25.8)
$ cat ./pipgrip.lock
botocore==1.13.48
docutils==0.15.2
jmespath==0.9.5
python-dateutil==2.8.1
six==1.14.0
urllib3==1.25.8
boto3==1.10.48
s3transfer==0.2.1
注意:由于所选的 botocore 版本比最新版本的 boto3 要求的版本旧,因此将检查所有 boto3 版本是否与 botocore==1.13.48 兼容。
版本冲突
如果给定(范围)包版本存在版本冲突,则会提出详细的解释。
$ pipgrip auto-sklearn~=0.6 dragnet==2.0.4
Error: Because dragnet (2.0.4) depends on scikit-learn (>=0.15.2,<0.21.0)
and auto-sklearn (0.6.0) depends on scikit-learn (<0.22,>=0.21.0), dragnet (2.0.4) is incompatible with auto-sklearn (0.6.0).
And because no versions of auto-sklearn match >0.6.0,<1.0, dragnet (2.0.4) is incompatible with auto-sklearn (>=0.6.0,<1.0).
So, because root depends on both auto-sklearn (~=0.6) and dragnet (==2.0.4), version solving failed.
注意:如果允许使用旧版本的 auto-sklearn,PubGrub 将尝试所有可接受的 auto-sklearn 版本。在这种情况下,auto-sklearn==0.5.2 需要 scikit-learn (<0.20,>=0.19),使其与 dragnet==2.0.4 兼容。
循环依赖
如果找到循环依赖关系,则会在结果树中注明。
$ pipgrip --tree -v keras==2.2.2
WARNING: Cyclic dependency found: keras depends on keras-applications and vice versa.
WARNING: Cyclic dependency found: keras depends on keras-preprocessing and vice versa.
keras==2.2.2 (2.2.2)
├── h5py (2.10.0)
│ ├── numpy>=1.7 (1.18.1)
│ └── six (1.14.0)
├── keras-applications==1.0.4 (1.0.4)
│ ├── h5py (2.10.0)
│ │ ├── numpy>=1.7 (1.18.1)
│ │ └── six (1.14.0)
│ ├── keras>=2.1.6 (2.2.2, cyclic)
│ └── numpy>=1.9.1 (1.18.1)
├── keras-preprocessing==1.0.2 (1.0.2)
│ ├── keras>=2.1.6 (2.2.2, cyclic)
│ ├── numpy>=1.9.1 (1.18.1)
│ ├── scipy>=0.14 (1.4.1)
│ │ └── numpy>=1.13.3 (1.18.1)
│ └── six>=1.9.0 (1.14.0)
├── numpy>=1.9.1 (1.18.1)
├── pyyaml (5.3)
├── scipy>=0.14 (1.4.1)
│ └── numpy>=1.13.3 (1.18.1)
└── six>=1.9.0 (1.14.0)
已知警告
- PubGrub 不支持版本epochs ,这是PyPA 选择resolvelib而不是 PubGrub 作为新解析器的主要原因。
- 包名称在轮元数据中被规范化,从而产生例如
path.py -> path-py
和keras_preprocessing -> keras-preprocessing
输出。 - VCS 支持:不支持将 VCS 要求与
--editable
、 以及@ -e svn+
模式结合使用。 - 与 setuptools' 类似,VCS 要求(如)和PEP 440直接引用(如)都不支持
install_requires
省略前缀。projectname @
pip install git+https...
pip install https...
- 解析需求文件 (
-r
) 不支持:自定义文件编码、行延续、全局/每个需求选项 --reversed-tree
尚未实施。- 由于
pip install -r
不接受作为要求,因此从输出.
中省略。--lock
所以在安装本地项目的时候,要么使用--pipe
要么--install
应该使用(后者基本可以pipgrip --lock . && pip install . --constraint ./pipgrip.lock
)。 - 不支持本地路径(如
pip install -e ../aiobotocore[boto3]
),当前目录除外(如pipgrip --install -e .[boto3]
)。
发展
运行make help
选项,例如为开发安装、linting 和测试。
也可以看看
BSD 3 条款许可证
版权所有 (c) 2020, ddelange
保留所有权利。