Conda:激活环境时发生了什么?

16

运行source activate <env-name>命令如何更新$PATH变量? 我一直在查看CONDA-INSTALLATION/bin/activate脚本,但不明白conda如何更新我的$PATH变量以包括最近激活环境的bin目录。我无法找到conda用于在$PATH变量前添加内容的代码。


您使用的conda版本是什么?在conda < 4.4和conda >= 4.4之间,行为已经发生了变化。 - darthbith
嗨,我正在运行4.4.8版本。谢谢! - Todd
1个回答

22

免责声明:我不是conda开发人员,也不是Bash专家。以下解释基于我对代码的追踪,希望我全部都理解正确。此外,下面所有链接都是指向写这篇答案时的主提交永久链接(7cb5f66)。行为/行可能会在未来的提交中更改。注意:前方深入的兔子洞!

请注意,此解释适用于命令source activate env-name,但在conda>=4.4中,激活环境的推荐方法是conda activate env-name。我认为,如果使用conda activate env-name,您应该从我们进入cli.main函数的部分开始阅读解释。

对于conda>=4.4且<4.5,查看CONDA_INST_DIR/bin/activate,我们在倒数第二和最后一行找到了以下内容(GitHub链接):

. "$_CONDA_ROOT/etc/profile.d/conda.sh" || return $?
_conda_activate "$@"

第一行会从$_CONDA_ROOT/etc/profile.d目录中引用脚本conda.sh,该脚本定义了_conda_activate bash函数,我们将参数$@传递给该函数,这基本上是我们传递给activate脚本的所有参数。

深入探究,我们看看$_CONDA_ROOT/etc/profile.d/conda.sh并找到(GitHub链接):

_conda_activate() {
# Some code removed...
    local ask_conda
    ask_conda="$(PS1="$PS1" $_CONDA_EXE shell.posix activate "$@")" || return $?
    eval "$ask_conda"

    _conda_hashr
}

重点是这一行代码:ask_conda=...,特别是$_CONDA_EXE shell.posix activate "$@"。在这里,我们使用参数shell.posixactivate运行conda可执行文件,然后是传递给此函数的其余参数(即我们要激活的环境名称)。
再深入一步......从这里开始,conda可执行文件调用cli.main function,因为第一个参数以shell.开头,它从conda.activate导入main函数。该函数创建Activator类的实例(定义在同一文件中),并运行execute方法。 < p > execute 方法处理参数并将传递的环境名称存储到实例变量中, 然后决定已传递activate命令, 因此运行activate方法

又迈入了兔子洞的一步...... activate 方法调用 build_activate 方法,该方法调用 另一个函数 处理环境名称以查找环境前缀(即环境所在的文件夹)。 最后,build_activate 方法将 prefix 添加到 PATH 通过 _add_prefix_to_path 方法。最后, build_activate 方法 返回要运行以“激活”环境的命令字典

而且更深入一步...从build_activate方法返回的字典由_yield_commands方法处理成shell命令,这些命令传递到_finalize方法中。 activate方法返回运行_finalize方法的值,该方法返回临时文件的名称。 临时文件具有设置所有适当环境变量所需的命令。
现在,回到activate.main函数,execute方法的返回值(即临时文件的名称)被打印到stdout。 这个临时文件名存储在_conda_activate Bash函数中的Bash变量ask_conda中,最后,eval Bash函数执行临时文件。

哎呀!我希望我把所有东西都搞对了。正如我所说,我不是一个conda开发人员,也远非Bash专家,所以请原谅我可能会有一些不完全正确的解释。如果有问题,请留言,我很乐意修复它!

我还应该指出,在conda >=4.4中激活环境的推荐方法是conda activate env-name,这也是这个过程如此复杂的原因之一 - 环境激活现在主要在Python中处理,而以前(我认为)它更多地直接在Bash/CMD中处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接