为啥 Pip 会忽略已配置的具有嵌套依赖项的存储库?

Posted

技术标签:

【中文标题】为啥 Pip 会忽略已配置的具有嵌套依赖项的存储库?【英文标题】:Why does Pip disregard configured repository with nested dependencies?为什么 Pip 会忽略已配置的具有嵌套依赖项的存储库? 【发布时间】:2020-05-12 21:38:51 【问题描述】:

问题

假设我在 Linux 机器上有一个完全空的 Python+Pip+R (pip 19.3.1) 环境,我想用 pip 安装包rpy2。由于我位于公司防火墙后面,因此我将 pip 配置为使用私有存储库。

[global]
index-url = http://private.com/artifactory/api/pypi/PyPI/simple
trusted-host = private.com

现在我执行pip install rpy2,我会得到以下错误:

Couldn't find index page for 'cffi'
 Download error on https://pypi.python.org/simple/

因此 pip 尝试通过从官方 PyPi 存储库中查找并安装 cffi 来解决嵌套依赖关系。它完全忽略了我配置的 repo。

当我一个接一个运行pip install cffi && pip install rpy2 时,一切都按预期运行。

这是完整的错误输出:

ERROR: Command errored out with exit status 1:
 command: /usr/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-8vuadu93/rpy2/setup.py'"'"'; __file__='"'"'/tmp/pip-install-8vuadu93/rpy2/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-8vuadu93/rpy2/pip-egg-info
     cwd: /tmp/pip-install-8vuadu93/rpy2/
Complete output (25 lines):
Download error on https://pypi.python.org/simple/cffi/: [Errno -2] Name or service not known -- Some packages may not be found!
Couldn't find index page for 'cffi' (maybe misspelled?)
Download error on https://pypi.python.org/simple/: [Errno -2] Name or service not known -- Some packages may not be found!
No local packages or working download links found for cffi>=1.13.1
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/tmp/pip-install-8vuadu93/rpy2/setup.py", line 183, in <module>
    'rinterface_lib/R_API_eventloop.h']
  File "/usr/lib/python3/dist-packages/setuptools/__init__.py", line 128, in setup
    _install_setup_requires(attrs)
  File "/usr/lib/python3/dist-packages/setuptools/__init__.py", line 123, in _install_setup_requires
    dist.fetch_build_eggs(dist.setup_requires)
  File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 513, in fetch_build_eggs
    replace_conflicting=True,
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 774, in resolve
    replace_conflicting=replace_conflicting
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 1057, in best_match
    return self.obtain(req, installer)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 1069, in obtain
    return installer(requirement)
  File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 580, in fetch_build_egg
    return cmd.easy_install(req)
  File "/usr/lib/python3/dist-packages/setuptools/command/easy_install.py", line 692, in easy_install
    raise DistutilsError(msg)
distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('cffi>=1.13.1')
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

问题

这是 Pip 中的错误、rpy2 的特定问题还是我遗漏了什么?

更新

运行以下命令给我同样的错误:

pip install rpy2 --no-index --find-links http://private.com/artifactory/api/pypi/PyPI/simple
pip install rpy2 --index-url http://private.com/artifactory/api/pypi/PyPI/simple

我使用了-vvv,似乎问题出现在setuptools内部的某个地方

解决方案

rpy2 使用setuptools 再次使用easy_install.py。它也适用于index_url 变量。但它不是从pip.config 而是从distutils.cfg 获取值。

我用find / -name "distutils" 识别了我安装的所有Python 版本。然后我将带有以下内容的distutils.cfg 添加到每个目录中:

[easy_install]
index_url = blablabla

现在它可以工作了,我执行pip install rpy2 并且所有缺少的需求都一次性安装了

【问题讨论】:

如果将配置设置指定为命令行参数会怎样?有什么区别吗?如果您还指定--no-index,会发生什么情况? 你试过在需求中指定私有索引吗? ***.com/questions/2477117/… 是的,我都试过了,但都没有积极的结果。我将完整的 Python 堆栈跟踪添加到我的帖子中 没有调查太深,但可能是因为cffi被列为setup_requires(当然也被列为install_requires)。如果在 pip 控制之外下载此依赖项,我不会感到惊讶。也许这会有所帮助:***.com/q/15014180/11138259 是的,就是这样!谢谢@sinoroc。您能否添加一个答案,以便我将问题标记为您已回答? 【参考方案1】:

我认为这可能是由于cffirpy2setup.py 中列为setup_requires 造成的。很可能是因为需要cffi 才能构建项目本身,然后才能安装。这种build依赖不是pip直接处理的,所以它的index-url选项没有作用。

解决方案是告诉 setuptools distutils configuration file中的替代索引

[easy_install]
index_url = https://my.index-mirror.com

参考资料:

"Controlling setup_requires" in pip's documentation setuptools, easy_install, and a custom pypi server distutils configuration file

【讨论】:

以上是关于为啥 Pip 会忽略已配置的具有嵌套依赖项的存储库?的主要内容,如果未能解决你的问题,请参考以下文章

如何导出具有依赖项的 SVN 存储库的一部分?

GNU Makefile - 具有一个依赖项的多个目标的模式规则忽略所有目标,但第一个

具有项目编译依赖项的 Gradle 嵌套多项目

如何在 Maven 中为依赖项指定存储库

来自私人 github 存储库的 Pip install wheel

如何创建具有基本依赖项的 deb 包?