Python setuptools:如何在 Nexus 上托管的私有 PyPI 存储库中指定依赖项?

问题描述

我无法构建依赖于私有 PyPI 存储库(托管在 Sonatype Nexus 存储库管理器,vOSS 3.17.0-01 上)中的包的 Python 轮子。

如果我使用pip,我可以搜索并安装该软件包;我的问题是试图让 setup.py 做同样的事情。通过查看各种命令的输出,我认为问题可能是由于存储库提供的包链接中的相对路径造成的。

搜索类似的问题,大多数都与私有 git 存储库有关。我能找到的最相关的相关问题是 Equivalent for `--find-links` in `setup.py`。该评论的正文指出

在 setuptools 上下文中,dependency_links 选项接受...包含直接下载链接的网页网址

但是,提供的链接页面支持该引用不再包含该文本(被更新的版本替换?)

所以这可能是问题所在 - 并且不支持我尝试做事的方式。如果是这种情况,有人可以提出一种有效的方法吗?

或者,这可能是 setuptools 中的错误,或者我们的 Nexus 的错误配置问题 - 如果有人可以证实或反驳这些理论 - 再次提出一种有效的方法 - 我会很感激。

这是我的设置和各种命令的输出显示了哪些有效,哪些无效:

  1. 设置环境:

    mkdir depends-fail
    cd depends-fail
    python3 -m venv venv
    source activate venv/bin/activate
    pip install --upgrade pip
    pip install wheel        # So we can use bdist_wheel build option.
    
  2. 确认我们当前的 pip 版本:

    (venv) $ pip --version
    pip 21.0.1 from /tmp/depends-fail/venv/lib/python3.6/site-packages/pip (python 3.6)
    
  3. 确认安装工具版本:

    (venv) $ python -c "import setuptools as s; print(s.version.__version__)"
    39.0.1
    
  4. depends-fail 目录中,创建这个最小的 setup.py 文件,它将演示问题:

     from setuptools import setup
     setup(
       name='Failed-dependencies',install_requires=['data-Feed-ping>=0.5'],dependency_links=[
         'http://nexus.example.local/nexus/repository/pypi-playground-public/simple/data-Feed-ping',]
    )
    
  5. 确认我们的依赖在我们的私有仓库中可用:

     (venv) $ pip search --trusted-host nexus.example.local \
     >  -i http://nexus.example.local/nexus/repository/pypi-playground-public/pypi \
     >  data-Feed-ping
    

    响应确认包在本地可用:

    ⋮
    Starting new HTTP connection (1): nexus.example.local:80
    http://nexus.example.local:80 "POST /nexus/repository/pypi-playground-public/pypi HTTP/1.1" 200 239
    data-Feed-ping (0.5)  - Determine response times of data Feeds.
    
  6. 当我们尝试构建并测试我们的最小包(它是触发依赖项下载的测试选项)时会发生什么:

    (venv) $ python setup.py bdist_wheel test
    

    包构建没有问题 - 但找不到依赖项:

        running bdist_wheel
        running build
        ⋮
        removing build/bdist.linux-x86_64/wheel
        running test
        Searching for data-Feed-ping>=0.5
    (1) Reading http://nexus.example.local/nexus/repository/pypi-playground-public/simple/data-Feed-ping
    (2) Downloading http://nexus.example.local/nexus/repository/packages/data-Feed-ping/0.5/data_Feed_ping-0.5-py3-none-any.whl#md5=e7a9ee0be6cc77165d02e7022c04b336
        error: Can't download http://nexus.example.local/nexus/repository/packages/data-Feed-ping/0.5/data_Feed_ping-0.5-py3-none-any.whl#md5=e7a9ee0be6cc77165d02e7022c04b336: \
        404 Repository not found
    
  7. (2) 中的下载链接和版本哈希来自在 (1) 处读取的索引 URL 的内容 - 让我们看看该文件是什么样的:

    (venv) $ curl http://nexus.example.local/nexus/repository/pypi-playground-public/simple/data-Feed-ping
    
    <html lang="en">
    <head><title>Links for data-Feed-ping</title><Meta name="api-version" value="2"/></head>
      <body><h1>Links for data-Feed-ping</h1>
        ⋮  <!-- links to prevIoUs versions -->
        <a href="../../packages/data-Feed-ping/0.5/data_Feed_ping-0.5-py3-none-any.whl#md5=e7a9ee0be6cc77165d02e7022c04b336" rel="internal">data_Feed_ping-0.5-py3-none-any.whl</a><br/>
      </body>
    </html>
    

索引 URL 确实提供了指向所需版本的 data-Feed-ping 包的链接,并且安装脚本正确地从该链接获取了 md5 摘要(请参阅脚本输出中的 (2))。但是,安装脚本随后会尝试从无效 URL 下载文件

对我来说,问题似乎出在索引链接提供的相对路径上。如果我们从索引 URL (1) 开始:

http://nexus.example.local/nexus/repository/pypi-playground-public/simple/data-Feed-ping

添加下载的相对路径:

../../packages/data-Feed-ping/0.5/data_Feed_ping-0.5-py3-none-any.whl#md5=e7a9ee0be6cc77165d02e7022c04b336

我得到以下绝对路径

http://nexus.example.local/nexus/repository/pypi-playground-public/packages/data-Feed-ping/0.5/data_Feed_ping-0.5-py3-none-any.whl#md5=e7a9ee0be6cc77165d02e7022c04b336

我已经确认绝对路径指向我想要的包:

(venv) $ wget http://nexus.example.local/nexus/repository/pypi-playground-public/packages/data-Feed-ping/0.5/data_Feed_ping-0.5-py3-none-any.whl#md5=e7a9ee0be6cc77165d02e7022c04b336

--2021-04-01 16:44:18--  http://nexus.example.local/nexus/repository/pypi-playground-public/packages/data-Feed-ping/0.5/data_Feed_ping-0.5-py3-none-any.whl
Resolving nexus.example.local (nexus.example.local)... 192.168.24.136
Connecting to nexus.example.local (nexus.example.local)|192.168.24.136|:80... connected.
HTTP request sent,awaiting response... 200 OK
Length: 19066 (19K) [application/zip]
Saving to: ‘data_Feed_ping-0.5-py3-none-any.whl’
data_Feed_ping-0.5-py3-none-any 100%[==========================================>]  18.62K  --.-KB/s    in 0s
2021-04-01 16:44:18 (76.3 MB/s) - ‘data_Feed_ping-0.5-py3-none-any.whl’ saved [19066/19066]

如果我尝试直接下载包,使用 pip 指定安装脚本使用的相同索引 URL,我也没有问题:

   (venv) $ pip install --trusted-host nexus.example.local \
   >  --index-url http://nexus.example.local/nexus/repository/pypi-playground-public/simple \
   >  data-Feed-ping

   Looking in indexes: http://nexus.example.local/nexus/repository/pypi-playground-public/simple
Collecting data-Feed-ping
   Downloading http://nexus.example.local/nexus/repository/pypi-playground-public/packages/data-Feed-ping/0.5/data_Feed_ping-0.5-py3-none-any.whl (19 kB)
   Requirement already satisfied: requests in ./venv/lib/python3.6/site-packages (from data-Feed-ping) (2.25.1)
   ⋮
   Installing collected packages: data-Feed-ping
   Successfully installed data-Feed-ping-0.5

解决方法

您应该只使用 pip(或任何其他安装程序)来安装 Python 项目。例如,通过调用 python setup.py install 进行安装是一种过时的做法(通常不起作用)。因此,因此,您可能应该删除 dependency_linkssetup.py 参数,并指示您的用户使用正确的 pip 标志进行安装,正如您在你的问题:

python -m pip install --trusted-host nexus.example.local \
   >  --index-url http://nexus.example.local/nexus/repository/pypi-playground-public/simple \
   >  data-feed-ping

以同样的方式 python setup.py test: 也已过时/弃用,建议您继续使用更现代的测试运行程序(pytest 是您想到的那个,但可能有其他人,也许是鼻子)。