Setuptools 平台特定的依赖

14

有没有办法告诉setuptools或distribute在特定平台上需要一个包?

在我的情况下,我正在使用readline,它作为Unix系统标准库的一部分提供,但在Windows上,我需要pyreadline模块来替换该功能(参见这个问题)。如果我只是将其放入要求中,它也会安装在完全无用的Unix系统上。

4个回答

22

尽管Martijn Pieters在当时给出的答案是完全有效的,但自那时以来Python打包方式已经发生了很多变化。

分发软件包的首选格式是使用wheel*。使用wheel无法在安装过程中运行Python代码。

Wheel使用在PEP 0427中规定的元数据版本二。环境标记可用于指定特定平台的依赖项。

Setuptools允许将这些环境标记指定为extras_require键。以下示例脚本依赖于Windows系统上的pyreadline和Linux发行版上的pyxdg

#!/usr/bin/env python
from setuptools import setup

setup(
    name='spam',
    version='0.0.1',
    extras_require={
        ':sys_platform == "win32"': [
            'pyreadline'
        ],
        ':"linux" in sys_platform': [
            'pyxdg'
        ]
    })

同时也要发布sdist,这样那些无法使用wheel的平台仍然可以安装你的软件包。


4
与其使用':sys_platform == "win32"',不如使用更易读和直观的方式'platform_system=="Windows"'。而且,与':"linux" in sys_platform'相比,你可以使用'platform_system=="Linux"'来代替。这将包括linuxlinux2。对于其他平台也是一样的,例如mac可以用'platform_system=="Darwin"'等等。参考资料:PEP 508,以及EasyBuilders - smac89
由于install_requiresextras_require都有处理特定平台的依赖项的机制,想知道哪个更建议使用?例如,在Pipenv中,仍存在一个问题需要支持在Pipfile中使用extras_require - Drake Guan
我的理解是:install_requires应该是需要与包一起存在,为包的生命周期和功能提供必要支持的包列表。这些包(install_requires)是补充所需包并为请求的包提供必要功能的。extras_require仅在用户请求额外功能时自行安装。setup_requires是设置脚本继续运行所必需的包(如果您正在重载安装命令,则需要此关键字)。 - user6767685
随着 PEP 496 和 508 的出现,不再需要使用 extras。我已经更新了我的答案,以符合 PEP 496 语法,并对 518 表示认同。 - Martijn Pieters

10
当我在2013年写下我的答案时,我们还没有PEP 496-环境标记PEP 508-用于Python软件包的依赖项规范。现在我们有了这些,答案是:在setup_requires中放置环境标记。
setup_requires = [
    'foo',
    'bar',
    'pyreadline; sys_platform == "win32"',
]

setup(
    # ...
    setup_requires=setup_requires,
)

这是自setuptools 20.6.8发布以来的支持,即2016年5月(支持在version 20.5中引入,但在其中间版本中曾短暂禁用)。
请注意,当执行时,setuptools将使用easy_install安装这些要求,这很难配置,因为使用pip安装项目时需要进行配置。
最好不要使用setuptools处理构建时依赖项,并使用遵循PEP 518 - 指定Python项目的最小构建系统要求的建议的pyproject.toml文件。 使用具有构建时依赖项的PEP 518构建系统意味着创建一个类似于此的pyproject.toml文件:
[build-system]
requires = [
    "setuptools",
    "wheel",
    "foo",
    "bar",
    "pyreadline; sys_platform == "win32",
]

这是与setup_requires相同的列表,但添加了setuptoolswheel。此语法由pip支持,截至版本10.0.0,于2018年3月发布。
以下是我在2013年的旧回答。

setup.py只是一个Python脚本。您可以在该脚本中创建动态依赖项:

import sys

setup_requires = ['foo', 'bar']

if sys.platform() == 'win32':
    setup_requires.append('pyreadline')

setup(
    # ...
    setup_requires=setup_requires,
)

7

其他答案也是正确的,如果需要支持旧版 setuptools,那么这些答案可能更方便,但是有一些进展:

最近版本的 setuptools 接受 PEP 508 样式的依赖项规范:

setup(
    # ...
    install_requires=[
        'pyreadline; platform_system == "Windows"',
    ],
)

选择正确的参数:

  • install_requires: 当前分发需要哪些其他分发才能正常工作
  • extras_require: 将可选功能的名称映射到其要求列表的字典
  • setup_requires: 其他必须存在的分发,以便设置脚本可以正确运行 注意:列在setup_requires中的项目不会自动安装。如果它们还没有本地可用,则它们将仅下载到./.eggs目录中。

还有一种通过setup.cfg文件提供这些参数的替代方法。请参阅文档以获取更多信息

PEP 518引入了一种新的、更强大的方式,可以在pyproject.toml文件中指定setup_requires

[build-system]
# Minimum requirements for the build system to execute.
requires = ['setuptools>"38.3.0"', 'wheel']  # PEP 508 specifications.

该功能已实现在pip 10.0.0b1中。使用它,用户将能够自动安装和更新构建系统要求。

2
from setuptools import setup


setup(
    install_requires=(['pymsgbox', 'PyTweening>=1.0.1', 'Pillow', 'pyscreeze']
                    + ["python3-xlib; sys_platform == linux"]
                    + ["python-xlib; sys_platform == linux2"]
                    + ["pyobjc-core; sys_platform == darwin"]
                    + ["pyobjc; sys_platform == darwing"]
                    ),
)

这将根据所使用的系统类型(linux2 适用于使用 python2 的 Linux 系统,linux 适用于使用 python3 的 Linux 系统,darwin 适用于 MacOS 系统),安装特定版本的库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接