conda 内部是如何工作的?

How does conda work internally?

我搜索了一段时间,没有找到满意的答案:

conda (http://conda.pydata.org) 在内部是如何工作的?欢迎任何细节...

此外,由于它是 python 不可知论者,而且显然工作得很好很流畅,为什么它不像 apt 或 yum 那样用作通用包管理器?

只使用 conda 作为包管理器有什么限制?有用吗?

或者反过来,为什么apt 和 yum 无法提供 conda 提供的功能? conda "better" 与那些包管理器相比还是不同?

感谢任何提示!

我不是软件方面的专家,但我一直在使用 conda 维护内部存储库几个月,所以我可以分享一个 "advanced user." 的见解这里有很多问题,所以我会尽量按顺序回答。

How does conda (http://conda.pydata.org) work internally? Any details are welcome...

我可以分享的最简明的参考是 conda-build doc,它详细解释了 conda 配方。

TL;DR Recipes 是带有配置文件 meta.yaml 的文件夹,该文件根据名称、版本、源位置、依赖项(构建、测试、运行)和基本测试来描述包安装后 运行。它还包含构建脚本(build.sh and/or bld.bat 分别用于 linux 和 win),它执行除下载源代码之外的任何构建步骤。

安装包括(简而言之)下载源代码、创建构建环境、构建、创建测试环境和测试。您可以在系统范围内安装某些东西,也可以在环境中安装它:

conda install -n myenv mypkg # install only in myenv
conda install mypkg # install globally

激活环境与使用 virtualenv 完全相同:

source activate myenv

What are the restrictions of using only conda as package manager? Would it work?

它会起作用的。如果您有支持您的环境的配方,则可以使用 conda 安装任何您想要的东西。您将 运行 解决的问题是包支持。 Conda 维护者和用户已经在各种渠道上创建了一个包生态系统,但对二进制包的支持几乎仅限于 Python 包通常需要的那些,其中许多仅在一个或两个平台上受支持。 apt、yum 等用户为各自的平台维护各种东西。

在我们的例子中,我们需要支持Ubuntu和OSX,所以我们通过puppet等愚蠢的法术维护了很多依赖于平台的二进制包,我们使用conda来维护Python 两个平台的包。如果我们使用的所有二进制包都存在 conda 包,我可能会考虑使用 conda 而不是 apt、brew 等,但如果我们使用的配方过时,我会冒着进行重大配方维护的风险。在 Python 包管理的情况下,这对我们来说很好,其中 conda 填补了一个巨大的空白,但我还没有准备好对我们有现有工具来维护的包进行处理。随着 conda 生态系统的成熟,我们将看看我的想法是否会改变。一个工具来统治它们会很好,但我认为 conda 还没有准备好让我实现这一跳跃。

Does it use some kind of containerization, or static linking of all the dependencies, why is it so "cross platform"?

"Cross-platform" 可以有很多含义。对于 Python 包,跨平台意味着您可以使用任何版本的 python 和您需要的包创建环境。对于 Linux/win 风格和发行版,您可以根据环境在构建脚本中执行任意操作。例如,看一下 conda build script for qt。它有适合 OSX 和 Linux 的安装。该脚本可以做任何它想做的事。您可以根据 OS 版本或任何您想要的版本进行切换。很多菜谱如果不支持安装平台就会直接失败

希望这对您有所帮助。

我在 SciPy 2014 talk 中对此进行了很多解释。让我在这里给出一个小提纲。

首先,conda 包非常简单。它只是要安装的文件的压缩包,以及 info 目录中的一些元数据。例如 python 的 conda 包是文件

的压缩包
info/
    files
    index.json
    ...
bin/
    python
    ...
lib/
    libpython.so
    python2.7/
        ...
    ...
...

您可以通过查看 Anaconda pkgs 目录中的解压包来准确了解它的外观。完整规范位于 https://docs.conda.io/projects/conda-build/en/latest/source/package-spec.html

当 conda 安装它时,它会将 tarball 提取到 pkgs 目录并将文件硬 links 到安装环境中。最后,一些具有一些硬编码安装路径的文件已被替换(通常是 shebang 行)。

基本上就是这样。在依赖项解析方面发生了更多的事情,但是一旦它知道要安装什么包,它就是这样做的。

构建包的过程稍微复杂一些。 @mattexx 的回答及其 links 的文档描述了一些使用 conda build 构建包的规范方法。

回答您的其他问题:

Furthermore, as it is python agnostic and apparently work so well and fluently, why is it not used as a general purpose package manager like apt or yum?

当然可以。唯一限制这一点的是为 conda 构建的软件包集。在 Windows 上,这是一个非常好的选择,因为没有像 Linux.

上那样的任何系统包管理器

What are the restrictions of using only conda as package manager? Would it work?

它会工作,假设你有你感兴趣的一切的 conda 包。主要限制是 conda 只想将东西安装到 conda 环境本身,所以需要系统上特定安装位置的东西可能不会非常适合 conda(尽管它仍然可行,如果您将该位置设置为您的环境路径)。或者,例如,conda 可能不是 "project level" 像 bower 这样的包管理器的合适替代品。

此外,除非您要构建一个明确使用 conda 作为包管理器的发行版。

关于这些事情我要说的主要是conda包通常被制作成可重定位,这意味着包的安装前缀无关紧要。这就是为什么在安装过程中更改硬编码路径的原因。这也意味着使用 conda build 构建的动态库将自动更改其 RPATH(在 Linux 上)和安装名称(在 OS X 上)以使用相对路径而不是绝对路径。

Or the other way round, why are e.g. apt and yum not able to provide the functionality conda provides? Is conda "better" than those package manager or just different?

在某些方面它更好,而在某些方面则不然。您的系统包管理器了解您的系统,并且其中有些包不会在 conda 中(有些包,如内核,可能不应该在 conda 中)。

conda 的主要优点是它的环境概念。由于包是可重定位的,你可以在多个地方安装同一个包,并且有效地完全独立安装所有东西,基本上是免费的。

Does it use some kind of containerization

不,唯一的 "containerization" 是拥有单独的安装目录并使软件包可重定位。

or static linking of all the dependencies,

依赖性 linking 完全取决于包本身。有些包静态 link 它们的依赖关系,有些则没有。动态 linked 库的加载路径已按照我上面描述的方式更改为可重定位。

why is it so "cross platform"?

"Cross platform" 在这种情况下表示 "cross operating system"。虽然同一个二进制包不能在 OS X、Linux 和 Windows 上工作,但关键是 conda 本身在这三个上的工作方式相同,所以如果你构建了相同的包对于所有三个平台,无论您在哪个平台上,您都可以以相同的方式管理它们。

我看到没有一个真正了解 conda 工作原理的人愿意分享他们的知识。这很不幸...

我可以提供 conda build 操作的高级序列:

  1. 查看meta.yaml找到运行 + BUILD deps
  2. 创建名为“_build”的新环境
    1. 安装 运行 + 来自 meta.yaml
    2. 的 BUILD 依赖项
  3. 获取源代码到 conda_bld/work
  4. 构建包:
    1. 获取 'snapshot1' 完整环境
    2. home_dir: 'conda_bld/work', 运行: 'sh build.sh' 'setup.py install conda_bld/work'(在本地安装到 _build env)
    3. 获取 'snapshot2' 完整环境
    4. 包裹内容为'diff snapshot1 snapshot2'
  5. 运行测试:
    1. 使用“{刚刚构建的包,运行 DEPS}”创建“_test”ENV
    2. 运行 次测试

旁边有 @asmeurer youtube link 应该可以帮助您入门。