【问题标题】:Differences between setuptools and pip's dependency resolutionsetuptools和pip的依赖解析的区别
【发布时间】:2013-08-31 00:26:21
【问题描述】:

我最近开始使用 SetupTools 打包我的第一个项目,并且大部分都取得了成功。

不幸的是,我遇到了一个令人困惑的情况——我的项目依赖于一个在 PyPI 上不可用的单文件模块。我已经能够使用 dependency_links 选项轻松地将 setup.py 配置为依赖于该模块,并且一切正常……只要我使用 setup.py 安装它。如果我尝试使用 pip 安装项目 egg,尝试安装模块时会失败,假设它必须是预制的 egg 存档。相比之下,setup.py 检测到它是一个简单的源文件并从中生成一个鸡蛋。

我的目标是让我的项目在 PyPI 上可用,因此仅使用 pip 即可安装它很重要;所以我的问题是……我做错了吗?

我的理解是 setuptools 本质上是达到目的的一种手段,目的是 pip 和 PyPI,所以这两个工具的行为方式如此不同对我来说似乎很奇怪。

setup.py 的相关部分和每个工具的输出如下:

setup(
    name='particle-fish',
    version='0.1.0',
    description='Python Boilerplate contains all the boilerplate you need to create a Python package.',
    long_description=readme + '\n\n' + history,
    author='Lachlan Pease',
    author_email='predatory.kangaroo@gmail.com',
    url='https://github.com/predakanga/particle-fish',
    packages=[
        'particle.plugins'
    ],
    include_package_data=True,
    install_requires=['particle', 'irccrypt', 'pycrypto'],
    dependency_links=['http://www.bjrn.se/code/irccrypt/irccrypt.py#egg=irccrypt-1.0'],
    license="BSD",
    zip_safe=False,
    keywords='particle-fish',
    classifiers=[
        'Development Status :: 2 - Pre-Alpha',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Natural Language :: English',
        "Programming Language :: Python :: 2",
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
    ],
    test_suite='tests',
    tests_require=['pytest', 'mock', 'coverage', 'pytest-cov'],
    cmdclass = {'test': PyTest},
)

setup.py install 的输出:

Installed /Users/lachlan/.virtualenvs/particle-fish/lib/python2.7/site-packages/particle_fish-0.1.0-py2.7.egg
Processing dependencies for particle-fish==0.1.0
Searching for irccrypt
Best match: irccrypt 1.0
Downloading http://www.bjrn.se/code/irccrypt/irccrypt.py#egg=irccrypt-1.0
Processing irccrypt.py
Writing /var/tmp/easy_install-svPfHF/setup.cfg
Running setup.py -q bdist_egg --dist-dir /var/tmp/easy_install-svPfHF/egg-dist-tmp-Xq3OCt
zip_safe flag not set; analyzing archive contents...
Adding irccrypt 1.0 to easy-install.pth file

pip 安装的输出:

Downloading/unpacking irccrypt (from particle-fish==0.1.0)
  Downloading irccrypt.py
  Cannot unpack file /private/var/tmp/pip-mCc6La-unpack/irccrypt.py (downloaded from /Users/lachlan/.virtualenvs/particle-staging/build/irccrypt, content-type: text/plain); cannot detect archive format
Cleaning up...
Cannot determine archive format of /Users/lachlan/.virtualenvs/particle-staging/build/irccrypt

【问题讨论】:

  • 你有哪些版本的 pip 和 setuptools?
  • Pip 版本 1.4.1 和 setuptools 版本分别为 0.9.8
  • 升级到 setuptools 1.1 然后重新运行 make sdist 结果相同

标签: python pip setuptools


【解决方案1】:

您的问题分为两部分:

  1. 处理通过setup指定的dependency_links的正确方法是什么?
  2. 为什么没有得到一致的处理?

处理通过setup指定的dependency_links的正确方法是什么?

The setuptools documentation 表示 dependency_links 参数的 setup 方法:

dependency_links
满足依赖项时要搜索的命名 URL 的字符串列表。如果需要安装由setup_requirestests_require 指定的软件包,将使用这些链接。它们还将被写入 egg 的元数据,供 EasyInstall 等工具在安装 .egg 文件时使用。

现在,这很模糊。他们确实提到了EasyInstall,因此我们可以深入研究那里的源代码以确定它如何处理dependency_links。 Setuptools 还记录了鸡蛋的内部结构,which includes the dependency-links.txt file 对应于 setupdependency_links 参数。它让我们更深入地了解链接实际上应该是什么:

依赖 URL 列表,每行一个,使用 dependency_links 关键字到 setup()这些可能是直接的 下载 URL,或包含直接下载的网页的 URL 链接,并将被 EasyInstall 用于查找依赖项,就像 用户通过--find-links 命令手动提供了它们 线选项。请参阅 setuptools 手册和 EasyInstall 手册 有关指定此选项的更多信息,以及有关 EasyInstall 如何处理--find-links URL。

(我的粗体强调)

这很有用,因为它指出了它们应该如何处理,以及它实际期望什么。这个描述比dependency_links 稍微有用,因为它指定了“要搜索的URLS”的实际含义:直接下载链接或包含它们的索引。源代码确认了--find-linksdependency_links are actually merged when building the egg,因此我们现在可以查看EasyInstall 的--find-links 参数以了解它的预期。

--find-links=URLS_OR_FILENAMES, -f URLS_OR_FILENAMES
扫描指定的“下载页面”或目录以获取指向 egg 或其他发行版的直接链接。

那里有更详细的信息,但总体思路是--find-links 正在寻找包含未找到的包的彩蛋或档案。所以这是你谜团答案的第一部分:dependency_links 用于指向完整的包,而不是单个未打包的模块。

这听起来像是 pip 如何处理您所包含的链接,当您通读所有内容时,这是有道理的。您可以通过查看 pip 的测试来确认这一点。 pip 有两个使用dependency_links 的测试(12),它们都假设dependency_links is pointing to an indexing page。这似乎符合 setuptools 的描述,其中dependency_links 是“命名要搜索的 URL 的字符串列表”。


所以,既然我们知道 pip 正在根据规范处理这个问题,那就留下第二个问题:

为什么要使用 setuptools?

为了了解为什么这与 setuptools 一起使用,您需要了解 setuptools 如何确定依赖项并尝试下载/安装它们。 PackageIndex.download method 在任何外部 url 上调用,并且需要在本地下载软件包才能安装。这个函数的文档字符串包含了我们问题的答案:

如果它是一个带有明确#egg=name-version 标记的.py 文件的URL(即,一个将- 转义为_ 的文件),则会在下载的文件旁边自动创建一个简单的setup.py

这解释了为什么 setuptools 忽略了它不是一个发行版但 pip 失败的事实。


TL;DR: dependency_links 应该指向包含一个包或存档,而不是未打包的模块。 Setuptools 意识到您的痛苦并帮助您解决问题,但这大多没有记录。如果许可允许,请考虑重新打包模块并将其包含在您的包中。

【讨论】:

    猜你喜欢
    • 2012-05-11
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 2018-10-20
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多