#

什么是包?#

包是一个压缩的 tarball 文件 (.tar.bz2) 或 .conda 文件,其中包含

  • 系统级库。

  • Python 或其他模块。

  • 可执行程序和其他组件。

  • info/ 目录下的元数据。

  • 直接安装到 install 前缀中的文件集合。

Conda 跟踪包和平台之间的依赖关系。 conda 包格式在平台和操作系统之间是相同的。

只有文件(包括符号链接)是 conda 包的一部分。 目录不包含在内。 目录会根据需要创建和删除,但您无法直接从 tar 存档创建空目录。

.conda 文件格式#

.conda 文件格式在 conda 4.7 中引入,作为 tarball 的更紧凑、因此更快的替代方案。

.conda 文件格式由一个外部的、未压缩的 ZIP 格式容器组成,其中包含 2 个内部压缩的 .tar 文件。

对于 .conda 格式的初始内部压缩格式支持,我们选择了 Zstandard (zstd)。 实际使用的压缩格式无关紧要,只要 libarchive 支持该格式即可。 压缩格式将来可能会随着更高级的压缩算法的开发而更改,并且无需更改 .conda 格式。 只需要更新 libarchive 即可将新的压缩格式添加到 .conda 文件。

这些压缩文件可能比其 bzip2 等效文件小得多。 此外,它们的解压缩速度也快得多。 .conda 是首选的文件格式(如果可用),尽管我们继续并行提供 .tar.bz2 文件。

阅读更多关于 .conda 文件格式的介绍 的信息。

注意

在 conda 4.7 及更高版本中,您不能使用以“.conda”结尾的包名称,因为它们与包的 .conda 文件格式冲突。

使用包#

  • 您可以搜索包

conda search scipy
  • 您可以安装包

conda install scipy
conda build my_fun_package

包结构#

.
├── bin
│   └── pyflakes
├── info
│   ├── LICENSE.txt
│   ├── files
│   ├── index.json
│   ├── paths.json
│   └── recipe
└── lib
    └── python3.5
  • bin 包含包的相关二进制文件。

  • lib 包含相关的库文件(例如 .py 文件)。

  • info 包含包元数据。

元包#

当 conda 包仅用于元数据,并且不包含任何文件时,它被称为元包。 元包可能包含对多个核心、底层库的依赖项,并且可以包含指向在执行时自动下载的软件文件的链接。 元包用于捕获元数据并简化复杂的包规范。

元包的一个示例是“anaconda”,它将 Anaconda Distribution 安装程序中的所有包收集在一起。 命令 conda create -n envname anaconda 创建一个与从 Anaconda Distribution 安装程序创建的环境完全匹配的环境。 您可以使用 conda metapackage 命令创建元包。 在命令中包含名称和版本。

Anaconda 元包#

Anaconda 元包用于创建 Anaconda Distribution 安装程序,以便它们具有一组与之关联的包。 每个安装程序版本都有一个版本号,该版本号对应于特定版本的特定包集合。 特定版本的包集合封装在 Anaconda 元包中。

Anaconda 元包包含几个核心、底层库,包括压缩、加密、线性代数和一些 GUI 库。

阅读更多关于 Anaconda 元包和 Anaconda Distribution 的信息.

互斥元包#

互斥元包是一个非常简单的包,它有一个名称。 它不需要有任何依赖项或构建步骤。 互斥元包通常是构建另一个包的某些变体的 recipe 中的“output”。 互斥元包充当一种工具,以帮助在具有不同名称的包之间实现互斥。

让我们看一些关于如何使用互斥元包针对不同的 BLAS 实现构建 NumPy 的示例。

使用 BLAS 变体构建 NumPy#

如果您使用 MKL 构建 NumPy,则还需要使用 MKL 构建 SciPy、scikit-learn 以及任何其他使用 BLAS 的内容。 重要的是要确保这些“变体”(使用特定选项集构建的包)一起安装,并且永远不要与备用 BLAS 实现一起安装。 这是为了避免崩溃、缓慢或数值问题。 对齐这些库既是构建时的问题,也是安装时的问题。 我们将展示如何使用元包来实现此需求。

让我们从元包 blas=1.0=mkl 开始: AnacondaRecipes/intel_repack-feedstock

请注意,mklblas 的字符串。

当有人使用 mkl-devel 包作为构建时依赖项时,该元包会自动添加为依赖项,使用 run_exportsAnacondaRecipes/intel_repack-feedstock

同样,这是 OpenBLAS 的元包: AnacondaRecipes/openblas-feedstock

以及 OpenBLAS 的 run_exports,作为 openblas-devel 的一部分: AnacondaRecipes/openblas-feedstock

从根本上说,conda 的互斥模型依赖于包名称。OpenBLAS 和 MKL 显然不是相同的包名称,因此它们不是互斥的。没有什么可以阻止 conda 同时安装两者。也没有什么可以阻止 conda 安装带有 MKL 的 NumPy 和带有 OpenBLAS 的 SciPy。元包是使我们能够实现互斥性的原因。它将选项统一在一个包名称下,但具有不同的构建字符串。使用 run_exports 自动添加元包有助于确保库使用者(依赖于库的包构建者)将拥有正确的依赖信息,以实现统一的运行时库集合。

安装带有 BLAS 变体的 NumPy#

要指定您想要的 NumPy 变体,您可以潜在地指定您想要的 BLAS 库

conda install numpy mkl

然而,这实际上并没有排除选择 OpenBLAS 的可能性。MKL 及其依赖项都不是互斥的(意味着它们没有相似的名称和不同的版本/构建字符串)。

此路径可能会导致一些模糊性和混合 BLAS 的解决方案,因此建议使用元包。要以非模糊的方式指定 MKL 驱动的 NumPy,您可以指定互斥包(直接或间接)

conda install numpy “blas=*=mkl”

然而,有一种更简单的方法来解决这个问题。例如,您可能想尝试另一个包,该包具有所需的互斥包作为依赖项。

OpenBLAS 通过其 “nomkl” 包实现了这一点: AnacondaRecipes/openblas-feedstock

任何东西都不应该使用 “nomkl” 作为依赖项。它严格来说是用户方便从 MKL(默认)切换到 OpenBLAS 的实用工具。

MKL 是如何成为默认值的?求解器需要一种方法来优先处理某些包而不是其他包。我们使用一个较旧的 conda 功能来实现这一点,该功能称为 track_features,最初用于不同的目的。

Track_features#

conda 的优化目标之一是尽量减少指定所需规格所需的 track_features 的数量。通过向一个或多个选项添加 track_features,conda 将降低其优先级或 “降低其权重”。优先级最低的包是将在环境中激活最多 track_features 的包。在许多变体中,默认包是激活最少 track_features 的包。

但有一个陷阱:任何 track_features 都必须是唯一的。没有两个包可以提供相同的 track_feature。因此,我们的标准做法是将 track_features 附加到与我们希望成为非默认项的元包相关联。

再看看 OpenBLAS 配方: AnacondaRecipes/openblas-feedstock

此附加的 track_features 条目是 MKL 被选择而不是 OpenBLAS 的原因。MKL 没有与之关联的任何 track_features。如果有 3 个选项,您将为默认选项附加 0 个 track_features,然后为下一个首选选项附加 1 个 track_features,最后为最不首选选项附加 2 个。但是,由于您通常只关心一个默认项,因此通常只需为默认选项以外的所有选项添加 1 个 track_feature 就足够了。

更多信息#

作为参考,Windows 上的 Visual Studio 版本对齐也使用互斥元包。 AnacondaRecipes/aggregate

Noarch 包#

Noarch 包是不特定于架构的包,因此只需构建一次。Noarch 包可以是通用的或 Python 的。Noarch 通用包允许用户在 conda 包中分发文档、数据集和源代码。Noarch Python 包如下所述。

meta.yamlbuild 部分中将这些包声明为 noarch 可以减少共享 CI 资源。因此,所有符合 noarch 包条件的包都应声明为 noarch 包。

Noarch Python#

build 部分中的 noarch: python 指令使纯 Python 包只需构建一次。

Noarch Python 包通过在安装时解决平台和 Python 版本特定的差异,减少了在不同架构和 Python 版本上构建多个不同纯 Python 包的开销。

为了符合 noarch Python 包的条件,必须满足以下所有条件

  • 没有编译的扩展。

  • 没有 post-link、pre-link 或 pre-unlink 脚本。

  • 没有特定于操作系统的构建脚本。

  • 没有特定于 Python 版本的 requirements。

  • 除了 Python 版本外,没有 skips。如果配方仅为 py3,请删除 skip 语句并在 host 和 run 部分添加 Python 版本约束。

  • 未使用 2to3。

  • setup.py 中未使用 Scripts 参数。

  • 如果 console_script entrypoints 在 setup.py 中,则它们在 meta.yaml 中列出。

  • 没有 activate 脚本。

  • 不是 conda 的依赖项。

注意

虽然 noarch: python 不适用于 selectors,但它适用于版本约束。 skip: True  # [py2k] 有时可以用 host 和 run 子部分中受约束的 Python 版本替换,例如: python >=3 而不仅仅是 python

注意

只有 console_script entry points 必须在 meta.yaml 中列出。其他 entry points 不与 noarch 冲突,因此不需要额外处理。

阅读有关 conda 的 noarch 包的更多信息。

更多信息#

有关更多信息,请深入了解我们的 管理包指南。在 包规范 中了解有关包元数据、存储库结构和索引以及包匹配规范的更多信息。