频道和生成索引#
频道布局#
.
├── channeldata.json
├── linux-32
| ├── repodata.json
│ └── package-0.0.0.tar.bz2
├── linux-64
| ├── repodata.json
│ └── package-0.0.0.tar.bz2
├── win-64
| ├── repodata.json
│ └── package-0.0.0.tar.bz2
├── win-32
| ├── repodata.json
│ └── package-0.0.0.tar.bz2
├── osx-64
| ├── repodata.json
│ └── package-0.0.0.tar.bz2
...
频道的一部分#
channeldata.json
包含有关频道的元数据,包括频道包含哪些子目录。
频道中存在哪些包,以及它们位于哪些子目录中。
子目录与平台相关联。例如,linux-64 子目录包含适用于 linux-64 系统的包。
repodata.json
包含子目录中包的索引。每个子目录将有自己的 repodata。频道在相应的子目录下包含包作为 tarball。
channeldata.json
#
{
"channeldata_version": 1,
"packages": {
"super-fun-package": {
"activate.d": false,
"binary_prefix": false,
"deactivate.d": false,
"home": "https://github.com/Home/super-fun-package",
"license": "BSD",
"post_link": false,
"pre_link": false,
"pre_unlink": false,
"reference_package": "win-64/super-fun-package-0.1.0-py310_0.tar.bz2",
"run_exports": {},
"subdirs": [
"win-64"
],
"summary": "A fun package! Open me up for rainbows",
"text_prefix": false,
"version": "0.1.0"
},
"subdirs": [
"win-64",
...
]
}
repodata.json
#
{
"packages": {
"super-fun-package-0.1.0-py310_0.tar.bz2": {
"build": "py37_0",
"build_number": 0,
"depends": [
"some-depends"
],
"license": "BSD",
"md5": "a75683f8d9f5b58c19a8ec5d0b7f796e",
"name": "super-fun-package",
"sha256": "1fe3c3f4250e51886838e8e0287e39029d601b9f493ea05c37a2630a9fe5810f",
"size": 3832,
"subdir": "win-64",
"timestamp": 1530731681870,
"version": "0.1.0"
},
...
}
如何生成索引#
对于每个子目录
查看子目录中存在的全部包。
生成要添加/更新/删除的包列表。
删除所有需要删除的包。
对于所有需要添加/更新的包
提取包以访问元数据,包括完整包名、文件修改时间 (
mtime
)、大小和index.json
。将包元数据聚合到 repodata 集合中。
应用 repodata 修补程序(补丁)。
计算并保存缩减的
current_index.json
索引。
示例:构建频道#
要构建本地频道并将包放入其中,请按照以下说明操作
创建频道目录。
$ mkdir local-channel $ cd local-channel
现在,下载您最喜欢的包。在我们的示例中,我们将使用 SciPy。接下来的步骤取决于您的平台
Windows
$ mkdir win-64 $ curl -L https://anaconda.org/anaconda/scipy/1.9.1/download/win-64/scipy-1.9.1-py310h86744a3_0.tar.bz2 -o win-64\scipy-1.9.1-py310h86744a3_0.tar.bz2
Linux
大多数 Linux 系统预装了
curl
。如果您还没有安装,请安装它。检查您是否拥有
curl
$ which curl
如果未找到
curl
,则安装它$ conda install curl
创建您要包含在频道中的包的本地副本
$ mkdir linux-64 $ curl -L https://anaconda.org/anaconda/scipy/1.9.1/download/linux-64/scipy-1.9.1-py310hd5efca6_0.tar.bz2 -o linux-64\scipy-1.9.1-py310hd5efca6_0.tar.bz2
macOS,英特尔芯片
$ mkdir osx-64 $ curl -L https://anaconda.org/anaconda/scipy/1.9.1/download/osx-64/scipy-1.9.1-py310h09290a1_0.tar.bz2 -o osx-64/scipy-1.9.1-py310h09290a1_0.tar.bz2
macOS,苹果芯片
$ mkdir osx-arm64 $ curl -L https://anaconda.org/anaconda/scipy/1.9.1/download/osx-arm64/scipy-1.9.1-py310h20cbe94_0.tar.bz2 -o osx-arm64/scipy-1.9.1-py310h20cbe94_0.tar.bz2
其他
要在上述列表中未包含的平台上查找最新的 SciPy,请访问 Anaconda 包文件列表,用于 SciPy.
运行 conda index。这将为频道生成
channeldata.json
以及 linux-64 和 osx-64 子目录的repodata.json
,以及其他一些文件$ conda index .
通过搜索频道检查您的工作
$ conda search -c file:/<path to>/local-channel scipy
SciPy 应该在几个频道中可用,包括
local-channel
。
幕后更多细节#
缓存包元数据#
缓存利用了现有的 repodata.json
文件(如果存在)。索引检查要更新哪些文件,其依据是自上次创建 repodata.json
以来哪些文件是新的、已删除或已更改的。当包是新的或已更改时,其元数据将被提取并缓存到该包所属的子目录中。子文件夹是 .cache
文件夹。此文件夹有一个我们感兴趣的文件:stat.json
,其中包含每个文件的 stat
命令的结果。这用于了解何时文件已更改并需要更新。在其他每个子文件夹中,每个包的提取的元数据文件都保存为原始包名加上 .json
扩展名。如果需要,拥有这些文件可以节省大量时间来完全重新创建索引。
题外话:.conda
包格式的一个设计目标是使索引尽可能快。为了实现这一点,.conda 格式将元数据与实际的包内容分开了。以前 .tar.bz2
容器需要提取整个包才能获得元数据,而新包格式允许提取元数据而不接触包内容。这使得索引速度与包大小无关。大型 .tar.bz2
包可能需要很长时间才能提取和索引。
通常,您无需手动更改缓存。要强制更新/重新扫描所有缓存的包,您可以删除 .cache 文件夹,或者只删除 .cache/stat.json
文件。理想情况下,您可以只从缓存中删除一个感兴趣的包,但此功能目前不存在。
Repodata 修补#
包 repodata 是从包内的 index.json 文件引导的。不幸的是,这些元数据并不总是正确的。有时需要追溯添加版本绑定。从包 index.json 文件中获取的值更改 repodata 的过程称为“热修复”。热修复很棘手,因为它有可能破坏已成功工作的环境,但有时也有必要修复已知无法工作的环境。
从 Python 脚本生成的 repodata 修补程序#
在您自己的服务器上,您可能可以运行您编写的任意 Python 代码来应用您的修补程序。这里的优势在于修补程序是在每次生成索引时动态生成的。这意味着自上次提交修补程序 Python 文件以来添加的任何新包都将被获取,并将对它们应用适当的热修复程序。
Anaconda 通过向 conda index
提供一个包含如何更改元数据的逻辑的 Python 文件来应用热修复程序。Anaconda 的热修复程序存储库位于 AnacondaRecipes/repodata-hotfixes
从 JSON 文件应用的 repodata 修补程序#
不幸的是,您不能总是直接运行您的 Python 代码 - 其他托管您修补程序的人员可能不允许您运行代码。您可以改为将修补程序打包为 .json 文件。这些文件将在应用时覆盖 repodata.json
中的条目。
例如,这是 conda-forge 必须采取的方法。他们的修补程序创建代码位于此处:conda-forge/conda-forge-repodata-patches-feedstock
该代码所做的是下载当前的 repodata.json
,然后运行他们的 Python 逻辑以生成修补程序 JSON 文件。这些修补程序将被放置到 Anaconda 的镜像工具将找到它们并将其应用于 conda-forge 的 repodata.json
的位置,时间为镜像时间。
这里的缺点是,此 JSON 文件与上次 repodata-patches feedstock 生成包的时间一样新。在此期间添加的任何新包都不会应用任何热修复程序,因为热修复程序 JSON 文件不知道这些文件。
修剪到“当前”repodata#
可用的包数量一直在增长。这意味着 conda 始终需要做更多工作。为了减缓这种增长,在 conda 4.7 中,我们添加了使用替代 repodata.json
文件的功能,这些文件可能代表正常 repodata.json
的子集。其中一个特别的是 current_repodata.json
,它表示
每个包的最新版本
使最新版本可满足的任何先前版本的依赖项
current_repodata.json
也只保留一种文件类型:.conda
(如果可用),以及 .tar.bz2
(如果只有 .tar.bz2
可用)。
对于 Anaconda 的默认“main”频道,current_repodata.json 文件的大小约为 repodata.json
的 1/7。这使得下载 repodata 速度更快,并且也使得将 repodata 加载到其 Python 表示形式的速度更快。
对于那些有兴趣了解如何实现这一点的人,请参阅 conda/conda-build 中的代码。