对于下游包作者#
本文档旨在解释编写依赖于 NumPy 的包的一些最佳实践。
了解 NumPy 的版本控制和 API/ABI 稳定性#
NumPy 使用一个标准,符合
PEP 440major.minor.bugfix
,版本控制方案: .主要版本非常不寻常(NumPy 仍处于 version ),如果发生,1.xx
则可能表明 ABI 中断。
次要版本会定期发布,通常每 6 个月发布一次。次要版本包含新功能、弃用和删除以前弃用的代码。错误修复版本的发布更加频繁;它们不包含任何新功能或弃用。
重要的是要知道,NumPy 与 Python 本身和大多数其他知名科学 Python 项目一样,不使用语义版本控制。相反,向后不兼容的 API 更改需要至少两个版本的弃用警告。有关更多详细信息,请参阅NEP 23 — 向后兼容性和弃用政策。
NumPy 同时具有 Python API 和 C API。 C API 可以直接使用,也可以通过 Cython、f2py 或其他此类工具使用。如果您的包使用 C API,那么 NumPy 的 ABI(应用程序二进制接口)稳定性很重要。 NumPy 的 ABI 向前兼容,但不向后兼容。这意味着:针对给定版本的 NumPy 编译的二进制文件仍可在较新的 NumPy 版本上正确运行,但在旧版本上则不然。
针对 NumPy 主分支或预发行版进行测试#
对于依赖于 NumPy 的大型、积极维护的软件包,我们建议在 CI 中针对 NumPy 的开发版本进行测试。为了使这一过程变得简单,夜间构建以轮子的形式提供,网址为 https://anaconda.org/scientific-python-nightly-wheels/。安装命令示例:
pip install -U --pre --only-binary :all: -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy
这有助于检测 NumPy 中需要在下一个 NumPy 版本之前修复的回归。此外,我们建议针对此作业在 CI 中提出警告错误,要么是所有警告,要么至少是DeprecationWarning
和
FutureWarning
。这将为您提供有关 NumPy 更改的早期警告,以适应您的代码。
添加对 NumPy 的依赖#
构建时依赖#
笔记
在 NumPy 1.25 之前,NumPy C-API 不向后兼容。这意味着当使用早于 1.25 的 NumPy 版本进行编译时,您必须使用您希望支持的最旧版本进行编译。这可以通过使用oldest-supported-numpy来完成 。请参阅NumPy 1.24 文档。
如果包直接使用 NumPy C API 或使用依赖于它的其他工具(如 Cython 或 Pythran),则 NumPy 是包的构建时依赖项。
默认情况下,NumPy 将公开一个向后兼容最旧 NumPy 版本的 API,该版本支持当前最旧的兼容 Python 版本。 NumPy 1.25.0 支持 Python 3.9 及更高版本,NumPy 1.19 是第一个支持 Python 3.9 的版本。因此,我们保证,在使用默认值时,NumPy 1.25 将公开与 NumPy 1.19 兼容的 C-API。 (确切的版本在 NumPy 内部头文件中设置)。
NumPy 还向前兼容所有次要版本,但主要版本将需要重新编译。
可以自定义默认行为,例如添加:
#define NPY_TARGET_VERSION NPY_1_22_API_VERSION
-D
在需要 NumPy C-API 的每个扩展模块中包含任何 NumPy 标头(或等效的编译器标志)之前。如果您需要以不兼容旧版本为代价使用新添加的 API,这主要有用。
如果由于某种原因您希望默认编译当前安装的 NumPy 版本,您可以添加:
#ifndef NPY_TARGET_VERSION
#define NPY_TARGET_VERSION NPY_API_VERSION
#endif
这允许用户通过 覆盖默认值-DNPY_TARGET_VERSION
。此定义对于每个扩展模块(使用
import_array()
)必须一致,并且也适用于 umath 模块。
当您针对 NumPy 进行编译时,您应该向您的文件添加适当的版本限制pyproject.toml
(请参阅 PEP 517)。由于您的扩展将与 NumPy 的新主要版本不兼容,并且可能与非常旧的版本不兼容。
对于 conda-forge 软件包,请参见 此处。
到目前为止,它通常很简单,只需包括:
host:
- numpy
run:
- {{ pin_compatible('numpy') }}
笔记
在 NumPy 1.25 发布时,NumPy 2.0 预计将成为 NumPy 的下一个版本。 NumPy 2.0 版本预计需要不同的引脚,因为需要 NumPy 2+ 才能与 NumPy 1.x 和 2.x 兼容。
运行时依赖和版本范围#
NumPy 本身和许多核心科学 Python 包已就放弃对旧 Python 和 NumPy 版本的支持的时间表达成一致:NEP 29 - 推荐 Python 和 NumPy 版本支持作为社区政策标准。我们建议所有依赖 NumPy 的软件包遵循 NEP 29 中的建议。
对于运行时依赖项install_requires
,请使用in指定版本边界
setup.py
(假设您使用numpy.distutils
或
setuptools
来构建)。
大多数依赖 NumPy 的库不需要设置版本上限:NumPy 会小心地保持向后兼容性。
也就是说,如果您(a)是一个保证频繁发布的项目,(b)使用了 NumPy 的大部分 API 接口,并且(c)担心 NumPy 中的更改可能会破坏您的代码,则可以设置一个上限N 不小于 3 的
界限,并且是 NumPy [ * ]的当前版本。如果您使用 NumPy C API(直接或通过 Cython),您还可以固定当前主要版本以防止 ABI 损坏。请注意,在 NumPy 上设置上限可能会影响您的库与其他较新的软件包一起安装的能力。<MAJOR.MINOR + N
MAJOR.MINOR
笔记
SciPy在此处提供了有关如何构建轮子以及处理其构建时和运行时依赖性的更多文档 。
NumPy 和 SciPy 轮构建 CI 也可以作为参考,可以在此处找到 NumPy, 在此处找到 SciPy。