有时我会遇到这样的情况:我有一个包可以依赖于包 A 或包 B。
例如,我的项目依赖于一个名为的包spam,如果将该项目重命名为pyspam,则我的项目可以依赖于spam或pyspam。
spam
pyspam
我无法弄清楚(或找不到)如何在 setup.py 中定义此类依赖项。解决这个问题的常用方法是什么?
编辑:我想在中定义依赖项setup.py。类似这样的事情:
setup.py
from setuptools import setup setup( name='myproject', install_requires=[ 'spam || pyspam' ] )
在 setup.py 中定义这种“任意其一”类型的依赖项并不完全受到官方支持,因此需要一些变通方法。通常有以下几种方法可以实现此目的:
extras_require
一种常见的解决方案是使用 extras_require 字段来定义额外的依赖项。这样,用户可以根据需要选择安装 spam 或 pyspam。
from setuptools import setup setup( name='myproject', install_requires=[ # 默认的依赖项(如果没有默认项,可为空) ], extras_require={ 'spam': ['spam'], 'pyspam': ['pyspam'], }, )
在这种情况下,用户可以选择在安装时指定额外的依赖项,例如:
pip install myproject[spam]
或
pip install myproject[pyspam]
这样可以给用户提供选择的机会。
另一种方法是使用 try-except 在 setup.py 中检查 spam 或 pyspam 是否已经安装,动态设置 install_requires:
try-except
install_requires
from setuptools import setup try: import spam required_package = 'spam' except ImportError: required_package = 'pyspam' setup( name='myproject', install_requires=[required_package], )
这个方法会在安装时检查是否已安装 spam,如果没有,则会将 pyspam 设置为依赖项。但请注意,这样的动态依赖在复杂环境下可能会产生不可预见的问题。
如果上述方法不符合项目需求,另一种方法是将依赖项的选择留给用户,即不在 setup.py 中定义可选依赖项,而是在项目文档中说明用户可以安装 spam 或 pyspam,例如:
# 安装说明 该项目依赖 `spam` 或 `pyspam` 包。请根据需要选择安装其中之一: ```bash pip install spam # 或者 pip install pyspam
```
这样做可以最大限度地保持 setup.py 的简单性,但依赖项的安装步骤需要用户手动执行。
pkg_resources
对于更复杂的依赖关系,可以考虑在运行时使用 pkg_resources 进行依赖项检查。