软件包规范#

软件包元数据#

info/ 目录包含有关软件包的所有元数据。此位置中的文件不会安装在安装前缀下。尽管您可以自由地将任何文件添加到此目录中,但 Conda 只会检查下面讨论的文件内容。

信息#

  • 文件

    • 软件包中的所有文件列表(不包括在 info/ 中)

  • index.json

    • 有关软件包的元数据,包括平台、版本、依赖项和构建信息

{
  "arch": "x86_64",
  "build": "py37hfa4b5c9_1",
  "build_number": 1,
  "depends": [
    "depend > 1.1.1"
  ],
  "license": "BSD 3-Clause",
  "name": "fun-packge",
  "platform": "linux",
  "subdir": "linux-64",
  "timestamp": 1535416612069,
  "version": "0.0.0"
}
  • paths.json

    • 软件包中的文件列表,以及它们关联的 SHA-256、大小(以字节为单位)和路径类型(例如硬链接与软链接)

{
  "paths": [
    {
      "_path": "lib/python3.7/site-packages/fun-packge/__init__.py",
      "path_type": "hardlink",
      "sha256": "76f3b6e34feeb651aff33ca59e0279c4eadce5a50c6ad93b961c846f7ba717e9",
      "size_in_bytes": 2067
    },
    {
      "_path": "lib/python3.7/site-packages/fun-packge/__config__.py",
      "path_type": "hardlink",
      "sha256": "348e3602616c1fe4c84502b1d8cf97c740d886002c78edab176759610d287f06",
      "size_in_bytes": 87519
    },
    ...
}

info/index.json#

此文件包含有关软件包的基本信息,例如名称、版本、构建字符串和依赖项。此文件的内容存储在 repodata.json 中,它是仓库索引文件,因此称为 index.json。JSON 对象是一个字典,包含下面显示的键。Conda 软件包的文件名由前 3 个值组成,例如:<name>-<version>-<build>.tar.bz2

类型

描述

name

字符串

软件包的小写名称。可以包含 "-" 字符。

version

字符串

软件包版本。不能包含 "-"。Conda 承认 PEP 440

build

字符串

构建字符串。不能包含 "-"。区分具有相同名称和版本的软件包的构建,例如

  • 使用其他依赖项的构建,例如 Python 3.4 而不是 Python 2.7。

  • 构建过程中的错误修复。

  • 一些不同的可选依赖项,例如 MKL 与 ATLAS 链接。Conda 中没有任何东西实际检查构建字符串。诸如 np18py34_1 之类的字符串仅用于人类可读性,Conda 永远不会解析它们。

build_number

整数

一个非负整数,表示软件包的构建号。

与构建字符串不同,构建号由 Conda 检查。Conda 使用它对具有相同名称和版本的软件包进行排序,以确定最新的软件包。这一点很重要,因为可能将包含对软件包构建方式的错误修复的新构建添加到仓库中。

depends

字符串列表

依赖项规范列表,其中每个元素都是一个字符串,如 软件包匹配规范 中所述。

arch

字符串

可选。软件包构建的架构。

示例:x86_64

Conda 目前不使用此键。

platform

字符串

可选。软件包构建的操作系统。

示例:osx

Conda 目前不使用此键。用于特定架构和平台的软件包通常由包含它们的仓库子目录区分---请参阅 仓库结构和索引

info/files#

列出作为软件包本身一部分的所有文件,每行一个。所有这些文件都需要链接到环境中。软件包中未在此文件中列出的任何文件在安装软件包时不会链接。info/files 中的文件目录分隔符始终应为 "/",即使在 Windows 上也是如此。这与 tarball 中使用的目录分隔符匹配。

info/has_prefix#

可选文件。列出所有包含硬编码构建前缀或占位符前缀的文件,这些文件需要在安装时用安装前缀替换。

注意

由于二进制替换的工作方式,占位符前缀必须长于安装前缀。

此文件中的每一行应该是一个路径,在这种情况下它被视为一个文本文件,默认占位符为 /opt/anaconda1anaconda2anaconda3,或者一个用空格分隔的占位符、模式和路径列表,其中

  • 占位符是构建或占位符前缀。

  • 模式为 textbinary

  • 路径是要更新的文件的相对路径。

示例:在 Windows 上

"Scripts/script1.py"
"C:\Users\username\anaconda\envs\_build" text "Scripts/script2.bat"
"C:/Users/username/anaconda/envs/_build" binary "Scripts/binary"

示例:在 macOS 或 Linux 上

bin/script.sh
/Users/username/anaconda/envs/_build binary bin/binary
/Users/username/anaconda/envs/_build text share/text

注意

相对路径的目录分隔符必须始终为 "/",即使在 Windows 上也是如此。占位符可以在 Windows 上包含 "\" 或 "/",但替换前缀将与占位符中使用的分隔符匹配。默认占位符 /opt/anaconda1anaconda2anaconda3 是一个例外,它将使用本机路径分隔符替换为安装前缀。在 Windows 上,占位符和路径始终出现在引号中以支持包含空格的路径。

info/license.txt#

可选文件。软件包的软件许可证。

info/about.json#

可选文件。包含 关于部分 中的条目 meta.yaml 文件。如果在构建配方中存在以下键,则会添加到 info/about.json

  • home

  • dev_url

  • doc_url

  • license_url

  • license

  • summary

  • description

  • license_family

info/recipe#

包含构建配方完整内容的目录。

meta.yaml.rendered#

完全渲染的构建配方。请参见 conda render

此目录仅在 构建部分 中的 include_recipe 标志为 True 时存在。

存储库结构和索引#

Conda 存储库 - 或通道 - 是一个目录树,通常通过 HTTPS 提供服务,它具有平台子目录,每个子目录都包含 conda 包和一个存储库索引。索引文件 repodata.json 列出了平台子目录中的所有 conda 包。使用 conda index 从目录内的 conda 包创建这样的索引。它只是将完整的 conda 包文件名映射到 info/index.json 中的字典对象,如 链接脚本 中所述。

在以下示例中,一个存储库在 64 位 Linux 和 32 位 Windows 上提供 conda 包 misc-1.0-np17py27_0.tar.bz2

<some path>/linux-64/repodata.json
                     repodata.json.bz2
                     misc-1.0-np17py27_0.tar.bz2
           /win-32/repodata.json
                   repodata.json.bz2
                   misc-1.0-np17py27_0.tar.bz2

注意

这两个 conda 包的文件名相同,并且仅通过包含它们的存储库子目录来区分。

包匹配规范#

此匹配规范与在命令行中使用 conda install 的语法不同,例如 conda install python=3.9。在内部,conda 将命令行语法转换为本节中定义的规范。

示例:python=3.9 转换为 python 3.9*。

包依赖项使用匹配规范指定。匹配规范是用空格分隔的 1、2 或 3 个部分的字符串

  • 第一部分始终是包的精确名称。

  • 第二部分指的是版本,可能包含特殊字符

    • | 表示 OR。

      示例:1.0|1.2 匹配版本 1.0 或 1.2

    • * 匹配版本字符串中的 0 个或多个字符。在正则表达式方面,它与 r.*```` 相同。

      示例:1.0|1.4* 匹配 1.0、1.4 和 1.4.1b2,但不匹配 1.2。

    • <、>、<=、>=、== 和 != 是版本的比较运算符,使用 PEP-440 进行比较。例如,<=1.0 匹配 0.90.9.11.0,但不匹配 1.0.1==!= 是精确相等。

      也支持预发布版本,这样 >1.0b4 将匹配 1.0b51.0rc1,但不匹配 1.0b41.0a5

      示例:<=1.0 匹配 0.9、0.9.1 和 1.0,但不匹配 1.0.1。

    • , 表示 AND。

      示例:>=2,<3 匹配 2 系列中的所有包。2.0、2.1 和 2.9 都匹配,但 3.0 和 1.0 不匹配。

    • , 的优先级高于 |,因此 >=1,<2|>3 表示大于或等于 1 且小于 2 或大于 3,匹配 1、1.3 和 3.0,但不匹配 2.2。

    Conda 通过将版本拆分为由 | 分隔的多个部分来解析版本。如果部分以 <、>、= 或 ! 开头,则将其解析为比较运算符。否则,将其解析为版本,可能包含 "*" 运算符。

  • 第三部分始终是精确的构建字符串。当有 3 个部分时,第二部分必须是精确的版本。

请记住,版本规范不能包含空格,因为空格用于在整个匹配规范中分隔包、版本和构建字符串。 python >= 2.7 是无效的匹配规范。此外,python>=2.7 匹配为名为 python>=2.7 的任何版本的包。

使用命令行时,请将任何包含空格字符或以下字符的包版本规范放在双引号中:<、>、* 或 |。

示例

conda install numpy=1.11
conda install numpy==1.11
conda install "numpy>1.11"
conda install "numpy=1.11.1|1.11.3"
conda install "numpy>=1.8,<2"

示例#

OR 约束 "numpy=1.11.1|1.11.3" 与 1.11.1 或 1.11.3 匹配。

AND 约束 "numpy>=1.8,<2" 与 1.8 和 1.9 匹配,但不匹配 2.0。

模糊约束 numpy=1.11 匹配 1.11、1.11.0、1.11.1、1.11.2、1.11.18 等等。

精确约束 numpy==1.11 匹配 1.11、1.11.0、1.11.0.0 等等。

构建字符串约束 "numpy=1.11.2=*nomkl*" 匹配不带 MKL 的 NumPy 1.11.2 包,但不匹配正常的 MKL NumPy 1.11.2 包。

构建字符串约束 "numpy=1.11.1|1.11.3=py36_0" 匹配为 Python 3.6 构建的 NumPy 1.11.1 或 1.11.3,但不匹配为 Python 3.5 或 Python 2.7 构建的任何版本的 NumPy。

以下是 numpy-1.8.1-py27_0 的所有有效匹配规范

  • numpy

  • numpy 1.8*

  • numpy 1.8.1

  • numpy >=1.8

  • numpy ==1.8.1

  • numpy 1.8|1.8*

  • numpy >=1.8,<2

  • numpy >=1.8,<2|1.9

  • numpy 1.8.1 py27_0

  • numpy=1.8.1=py27_0

版本排序#

class VersionOrder(object) 实现版本字符串之间的排序关系。

版本字符串可以包含通常的字母数字字符 (A-Za-z0-9),通过点和下划线分隔为多个组件。不允许空段(即两个连续的点,一个前导/尾随下划线)。一个可选的纪元号 - 一个整数后跟 ! - 可以位于实际版本字符串之前(这对于指示版本方案本身的更改很有用)。版本比较不区分大小写。

支持的版本字符串#

Conda 支持六种类型的版本字符串

  • 发布版本仅包含整数,例如 1.02.3.5

  • 预发布版本使用额外的字母,例如 arc,例如 1.0a11.2.beta32.3.5rc3

  • 开发版本由字符串 dev 表示,例如 1.0dev422.3.5.dev12

  • 发布后版本由字符串 post 表示,例如 1.0post12.3.5.post2

  • 标记版本具有指定特定感兴趣属性的后缀,例如 1.1.parallel。标记可以添加到上述 4 种类型中的任何一种。就排序而言,标记被视为预发布版本中的字符串。

  • 一个可选的本地版本字符串,用 + 分隔,可以附加到主(上游)版本字符串。仅当主版本相等时才会在比较中考虑它,但在其他情况下以完全相同的方式处理。

可预测的版本排序#

为了获得可预测的版本排序,保持给定软件包的版本号方案随时间保持一致至关重要。Conda 认为预发布版本小于发布版本。

  • 版本字符串应始终具有相同数量的组件(除了可选的标记后缀或本地版本字符串)。

  • 表示非发布版本的字母/字符串应始终出现在相同的位置。

在比较之前,版本字符串将按如下方式解析

  • 它们首先分别在 !+ 处拆分为纪元、版本号和本地版本号。如果没有 !,则纪元设置为 0。如果没有 +,则本地版本为空。

  • 然后,版本部分在 ._ 处拆分为多个组件。

  • 每个组件再次拆分为数字和非数字的运行

  • 仅包含数字的子组件将转换为整数。

  • 字符串转换为小写,对 devpost 进行特殊处理。

  • 当组件以字母开头时,会插入填充值 0 以保持数字和字符串的同步,从而得到 1.1.a1' == 1.1.0a1'

  • 本地版本部分也是如此。

示例

1.2g.beta15.rc  =>  [[0], [1], [2, 'g'], [0, 'beta', 15], [0, 'rc']]

1!2.15.1_ALPHA  =>  [[1], [2], [15], [1, '_alpha']]

生成的列表按字典顺序比较,对每对相应的子组件应用以下规则

  • 整数按数字比较。

  • 字符串按字典顺序比较,不区分大小写。

  • 字符串小于整数,但以下情况除外

    • dev 版本小于所有其他类型的对应版本。

    • post 版本大于所有其他类型的对应版本。

  • 如果子组件没有对应项,则将缺失的对应项视为整数 0,以确保 '1.1' == 1.1.0'

最终的顺序为

  0.4
< 0.4.0
< 0.4.1.rc
== 0.4.1.RC   # case-insensitive comparison
< 0.4.1
< 0.5a1
< 0.5b3
< 0.5C1      # case-insensitive comparison
< 0.5
< 0.9.6
< 0.960923
< 1.0
< 1.1dev1    # special case ``dev``
< 1.1a1
< 1.1.0dev1  # special case ``dev``
== 1.1.dev1   # 0 is inserted before string
< 1.1.a1
< 1.1.0rc1
< 1.1.0
== 1.1
< 1.1.0post1 # special case ``post``
== 1.1.post1  # 0 is inserted before string
< 1.1post1   # special case ``post``
< 1996.07.12
< 1!0.4.1    # epoch increased
< 1!3.1.1.6
< 2!0.4.1    # epoch increased again

一些软件包(最显著的是 OpenSSL)具有不兼容的版本约定。特别是,OpenSSL 将字母解释为版本计数器而不是预发布标识符。对于 OpenSSL,关系 1.0.1 < 1.0.1a   =>   True   # for OpenSSL 成立,而 conda 包使用相反的排序。可以通过在普通版本号后面附加破折号来解决此问题

1.0.1a  =>  1.0.1post.a      # ensure correct ordering for OpenSSL