【发布时间】:2013-04-09 22:36:03
【问题描述】:
有没有办法告诉 setuptools 或分发需要特定平台上的包?
在我的具体情况下,我使用 readline,它是 Unix 系统标准库的一部分,但在 Windows 上,我需要 pyreadline 模块来替换该功能(参见 this question)。如果我只是把它放在要求它也安装在它完全没用的Unix系统上。
【问题讨论】:
标签: python setuptools
有没有办法告诉 setuptools 或分发需要特定平台上的包?
在我的具体情况下,我使用 readline,它是 Unix 系统标准库的一部分,但在 Windows 上,我需要 pyreadline 模块来替换该功能(参见 this question)。如果我只是把它放在要求它也安装在它完全没用的Unix系统上。
【问题讨论】:
标签: python setuptools
当我在 2013 年第一次在这里写答案时,我们还没有 PEP 496 – Environment Markers 和 PEP 508 – Dependency specification for Python Software Packages。既然我们这样做了,答案是:将环境标记放入您的setup_requires:
setup_requires = [
'foo',
'bar',
'pyreadline; sys_platform == "win32"',
]
setup(
# ...
setup_requires=setup_requires,
)
从 2016 年 5 月发布的 setuptools 20.6.8 开始支持此功能(在 version 20.5 中引入了支持,但在中间版本中被短暂禁用)。
请注意,setuptools 在执行时将使用easy_install 安装这些需求,而使用pip 安装项目时很难配置。
最好不使用 setuptools 来处理构建时依赖项,并按照PEP 518 – Specifying Minimum Build System Requirements for Python Projects 的建议使用pyproject.toml 文件。使用带有内置依赖项的 PEP 518 构建系统,意味着创建一个看起来像这样的pyproject.toml 文件:
[build-system]
requires = [
"setuptools",
"wheel",
"foo",
"bar",
"pyreadline; sys_platform == "win32",
]
这与setup_requires 相同,但添加了setuptools 和wheel。自 2018 年 3 月发布的 version 10.0.0 起,pip 支持此语法。
我从 2013 年开始的旧答案如下。
setup.py 只是一个 python 脚本。您可以在该脚本中创建动态依赖项:
import sys
setup_requires = ['foo', 'bar']
if sys.platform() == 'win32':
setup_requires.append('pyreadline')
setup(
# ...
setup_requires=setup_requires,
)
【讨论】:
如果需要支持旧的setuptools 版本,其他答案是有效的并且可能更方便,但已经取得了一些进步:
最新版本的 setuptools 接受 PEP 508 样式依赖规范:
setup(
# ...
install_requires=[
'pyreadline; platform_system == "Windows"',
],
)
选择合适的参数:
install_requires:当前发行版还需要哪些其他发行版才能正常工作extras_require:将可选功能的名称映射到其需求列表的字典setup_requires: 需要存在的其他发行版才能正确运行安装脚本
注意:setup_requires 中列出的项目不会自动安装。如果它们在本地不可用,则只需将它们下载到 ./.eggs 目录即可。还有另一种方法可以通过setup.cfg 文件提供这些参数。 See the documentation for more info.
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 中实现。使用它可以自动安装和更新构建系统要求。
【讨论】:
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 系统)
【讨论】:
虽然 Martijn Pieters 给出的 answer 在当时是完全有效的,但 Python 封装从那时起发生了很大变化。
分发包的首选格式是使用wheels*。使用轮子在安装期间无法运行 Python 代码。
Wheel 使用PEP 0427 中指定的元数据版本二。 Environment markers 可用于指定平台特定的依赖关系。
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的平台仍然可以安装你的包。
【讨论】:
':sys_platform == "win32"',写起来更易读、更直观,'platform_system=="Windows"'。而不是':"linux" in sys_platform',您可以使用'platform_system=="Linux"'。这将包括linux 和linux2。其他平台也一样,mac是'platform_system=="Darwin"'等。参考:PEP 508和EasyBuilders
install_requires 和extras_require 都具有特定于平台的依赖机制,只是想知道建议使用哪一个?比如Pipenv中,Pipfile中支持extras_require还有一个问题~
install_requires 应该是一个需要与包一起存在的包的列表,为了包的生命周期,为了包的功能。此软件包列表 (install_requires) 是对所需软件包的补充,并为请求的软件包提供必要的功能。 extras_require 仅在用户请求附加功能时自行决定安装。 setup_requires 是安装脚本继续运行所必需的包(如果您正在重载安装命令,则需要密钥)