setuptools和pip的依赖关系解析之间的差异

时间:2013-08-31 00:26:22

标签: python pip setuptools

我最近开始使用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 install的输出:

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

1 个答案:

答案 0 :(得分:3)

您的问题分为两部分:

  1. 通过dependency_links处理setup的正确方法是什么?
  2. 为什么不能持续处理?

  3. 通过dependency_links处理setup来处理dependency_links的正确方法是什么?

    The setuptools documentationsetup menthod的dependency_links参数说明了这一点:

      

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

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

      

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

    (大胆强调我的)

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

      

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

    那里有更详细的信息,但一般的想法是--find-links 正在寻找包含未找到的包的鸡蛋或档案。因此,您的神秘答案的第一部分是: dependency_links用于指向完整的包,而不是单独的未打包的模块。

    这听起来像pip处理你所包含的链接,这在你阅读所有内容时都有意义。您可以通过查看pip具有的测试来确认这一点。 pip有两个使用dependency_links12)的测试,两者都假定为dependency_links is pointing to an indexing page。这似乎与setuptools中的描述一致,其中dependency_links是“命名要搜索的URL的字符串列表”。


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

    为什么这适用于setuptools?

    为了理解为何使用setuptools,您需要了解setuptools如何确定依赖关系并尝试下载/安装它们。在任何外部网址上调用PackageIndex.download method,并要求在本地下载软件包进行安装。该函数的docstring包含我们问题的答案:

      

    如果是具有明确#egg=name-version标记的.py文件的网址(即,-全部为_,则为setup.py)与下载的文件一起自动创建。

    这就解释了为什么setuptools忽略了它不是分布的事实,但是pip失败了。


    TL; DR: dependency_links应指向包含一个的包或存档,而不是未打包的模块。 Setuptools实现了你的痛苦并帮助你,但这几乎没有记录。如果许可证允许,请考虑重新打包模块并将其包含在您的软件包中。