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

Lac*_*ase 5 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},
)
Run Code Online (Sandbox Code Playgroud)

setup.py安装的输出:

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

Kev*_*own 4

您的问题有两个部分:

\n\n
    \n
  1. dependency_links处理指定通过的正确方法是什么setup
  2. \n
  3. 为什么这个问题没有得到一致的处理?
  4. \n
\n\n
\n\n

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

\n\n

setuptools 文档dependency_links对mentod 的参数进行了如下说明setup

\n\n
\n

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

\n
\n\n

现在,这是相当模糊的。他们确实提到了EasyInstall,所以我们可以深入研究那里的源代码来确定它是如何处理的dependency_links。setuptools 还记录了 Eggs 的内部结构,其中dependency-links.txt包括dependency_links. setup它让我们更深入地了解链接实际上应该是什么:

\n\n
\n

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

\n
\n\n

(粗体强调我的)

\n\n

这很有用,因为它指出了应该如何处理它们,以及它实际期望什么。这一描述比上一描述稍微有用dependency_links,因为它指定了“要搜索的 URL”的实际含义:直接下载链接或包含它们的索引。源代码证实了--find-linksdependency_links 实际上是在构建 Egg 时合并的,因此我们现在可以查看--find-linksEasyInstall 的参数以了解其期望的内容。

\n\n
\n

--find-links=URLS_OR_FILENAMES, -f URLS_OR_FILENAMES
\n 扫描指定的 \xe2\x80\x9c 下载页面\xe2\x80\x9d 或目录以获取 Egg 或其他发行版的直接链接。

\n
\n\n

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

\n\n

这听起来像是 pip 处理您所包含的链接的方式,当您通读所有内容时,这是有意义的。您可以通过查看 pip 的测试来确认这一点。pip 有两个使用dependency_links( 1 , 2 ) 的测试,这两个测试都假设dependency_links指向索引页。这似乎符合 setuptools 的描述,其中dependency_links是“命名要搜索的 URL 的字符串列表”。

\n\n
\n\n

所以,现在我们知道 pip 正在根据规范处理这个问题,剩下第二个问题:

\n\n

为什么这与 setuptools 一起工作?

\n\n

为了理解为什么 setuptools 可以这样做,您需要了解 setuptools 如何确定依赖项并尝试下载/安装它们。该PackageIndex.download方法会在任何外部 URL 上调用,并且需要在本地下载软件包才能安装。该函数的文档字符串包含我们问题的答案:

\n\n
\n

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

\n
\n\n

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

\n\n
\n\n

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

\n