在setup.py中表达特定于平台的依赖关系是否可能,而不构建特定于平台的egg版本?

45

我们有一个占位符egg,其中不包含任何代码,只是为了从我们的PyPi存储库中拉取依赖包列表而存在。

这些依赖包大多数是平台无关的,但有些仅在Win32平台上使用。

是否可能以某种方式使依赖项平台条件化,以便在安装于Win32时给定安装install_requires列表中的依赖项仅被拉取下来?

或者: 是否可以指定一组可选的依赖项,如果可用则会安装,但如果它们不存在也不会导致easy_install失败?

4个回答

55

关于从sdist、egg和wheel发布中的平台特定依赖项: https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#platform-specific-dependencies

有时候,一个项目可能需要在特定的平台上运行某个依赖项。这可能是将模块回溯到旧版本的Python中使用的包,也可能是要求在特定操作系统上运行的包。这将允许项目在多个不同的平台上工作,而不必安装对于正在安装项目的平台不需要的依赖项。

setup(
    name="Project",
    ...
    install_requires=[
        'enum34 ; python_version<"3.4"',
        'pywin32 >= 1.0 ; platform_system=="Windows"'
    ]
)

2
顺便提一下,特殊变量 python_versionplatform_system 在此之前不需要初始化。PEP 508 提供了可用变量的列表。 - rvf
为了指定依赖项的平台和Python版本,您可以使用and,参见此问题 - Wisco crew

12

setup.py中:

from setuptools import setup
import sys

setup(
    name="...",
    install_requires=["This", "That"] + (
        ["WinOnly", "AnotherWinOnly"] if sys.platform.startswith("win") else []
        )
)

distutils.util.get_platform如果需要的话,可以提供比sys.platform更多的信息:

>>> sys.platform
'linux2'
>>> distutils.util.get_platform()
'linux-i686'

5
假设这个逻辑生成的依赖列表将被嵌入到我的egg元数据中,这意味着如果我在Windows上构建 egg,则它将具有Windows依赖项,然后在Linux上安装时会因为缺少这些依赖项而失败? - Daniel Fortunov
我不确定它是如何工作的。我假设由于“setup.py”在安装时执行,因此依赖项将在安装时生成。但这应该很容易测试。 - codeape
3
请注意,平台检查应为if sys.platform == 'win32',否则它将在Mac OS X(darwin)上通过。参见https://dev59.com/aXI95IYBdhLWcg3wzRXv - kraymer
3
这样不行。除非你进行源代码安装,否则setup.py在安装时不会被执行,它只会在打包时被执行。我建议重新考虑其他解决方案。 - jpmc26

11

使用extras_require分发选项,将“win32支持”作为可选功能:

setup(
  ...
  extras_require={
    'win32': 'pywin32'
  },
  ...
)

在Windows上安装时,请指定win32特性:

easy_install mypackage[win32]
这将下载“pywin32”包,该包被列为'mypackage'的“win32”功能所依赖的内容。
有关可选功能的更多信息,请参见此处

2
当使用python setup.py bdist_egg命令构建蛋文件时,你可以强制setuptools/distribute构建平台特定的蛋文件。
from setuptools import setup
import os

# Monkey-patch Distribution so it always claims to be platform-specific.
from distutils.core import Distribution
Distribution.has_ext_modules = lambda *args, **kwargs: True

requirements = ['generic-foo', 'generic-bar']

if os.getenv('WINDOWS_BUILD'):
    requirements.extend(['a-windows-only-requirement'])

setup(
    name="...",
    install_requires=requirements
)

您可以运行:

# Force a windows build
$ WINDOWS_BUILD=y python setup.py bdist_egg -p win32
# Do a linux build -- you may not need to specify -p if you're happy
# with your current linux architecture.
$ python setup.py bdist_egg -p linux-i686

这很hacky; 另外,问题指定不要构建特定于平台的 eggs! - Daniel Fortunov
有点棘手,但在我的情况下很有用。谢谢。 - Hamlett

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