conda init
和 conda activate
#
conda
默认情况下提供了虚拟环境。 当您安装 Anaconda 或 Miniconda 时,您会获得一个 base
环境,它本质上是一个带有额外检查的常规环境。 这些检查与 conda
命令的实际含义以及它如何在您的系统中安装有关。
基本前缀与目标前缀
最初,conda
的基本安装被称为根环境。 所有其他环境都位于该根环境的 envs/
下。 根环境后来被重命名为base,但代码仍然使用旧的术语区分基本环境和目标环境。
context.root_prefix
:base
Conda 安装所在的路径。context.target_prefix
:conda
正在运行命令的环境。 通常默认为激活的环境,除非在命令行中指定了-n
(名称)或-p
(前缀)。 请注意,如果您正在操作base
环境,则目标前缀将与根前缀具有相同的值。
当您在终端中键入 conda
时,您的 shell 会尝试找到:
一个名为
conda
的 shell 函数一个名为
conda
的可执行文件,位于您的PATH
目录中
如果您的 conda
安装已正确初始化,它将找到 shell 函数。 如果没有,它可能会找到 conda
可执行文件(如果它恰好在 PATH
中),但这通常不是这种情况。 这就是初始化存在的首要原因!
Conda 初始化#
为什么一开始就需要初始化? 有几个原因:
激活需要非常密切地与 shell 上下文进行交互
它不会不必要地污染
PATH
提高某些操作的性能
初始化背后的主要思想是提供一个 conda
shell 函数,它允许 Python 代码更密切地与 shell 上下文进行交互。 它还允许更干净的 PATH
操作以及某些 conda
命令的更快速响应。
conda
shell 函数主要是转发函数。 它会将大多数命令委托给由 Python 库驱动的真实 conda
可执行文件。 但是,它将拦截两个非常特定的子命令:
conda activate
conda deactivate
需要这种拦截,因为激活/停用需要将环境变量导出(或取消设置)回 shell 会话(而不仅仅是在 Python 进程中临时进行)。 这将在下一节中讨论。
那么如何进行初始化呢? 这是 conda init
子命令的工作,它由 conda.cli.main_init
模块驱动,该模块直接依赖于 conda.core.initialize
模块。 让我们看看它是如何实现的。
conda init
将通过在您 shell 的相关启动脚本(例如 ~/.bashrc
)中写入一些 shell 代码来永久初始化 shell。
这通过
conda.core.initialize
中定义的不同函数来完成,具体如下:init_sh_user
:为当前用户初始化 Posix shell(如 Bash)。init_sh_system
:为所有用户全局初始化 Posix shell(如 Bash)。init_fish_user
:为当前用户初始化 Fish shell。init_xonsh_user
:为当前用户初始化 Xonsh shell。init_cmd_exe_registry
:通过 Windows 注册表初始化 Cmd.exe。init_powershell_user
:为当前用户初始化 Powershell。
init_long_path
:配置 Windows 以支持更长的路径。
每个函数的作用取决于每个 shell 的性质。对于 Bash shell,底层 Activator
子类(下面将详细介绍)可以动态生成钩子代码。在其他 Posix shell 和 Powershell 中,从其在 base
环境中的位置获取脚本。对于 Cmd,通过 Windows 注册表引入更改。最终结果相同:它们将最终定义一个具有上述行为的 conda
shell 函数。
Conda activate#
所有
Activator
类都可以在conda.activate
下找到。它们的工作本质上是通过编程方式编写 shell 本地代码。从 conda 4.11 开始,以下列出了支持的 shell 及其相应的激活器:posix
、ash
、bash
、dash
、zsh
:均由PosixActivator
驱动。csh
、tcsh
:CshActivator
。xonsh
:XonshActivator
。cmd.exe
:CmdExeActivator
。fish
:FishActivator
。
powershell
:PowerShellActivator
。
您可以通过
conda shell.<key>
命令添加所有这些类,其中key
是上面列表中的任何名称。这些 CLI 接口提供多个子命令,直接连接到同名方法。activate
:编写 shell 代码以激活给定环境。deactivate
:编写 shell 代码以停用给定环境。hook
:编写 shell 代码以注册conda
shell 代码的初始化代码。commands
:编写自动完成引擎所需的 shell 代码。
reactivate
:编写停用后激活的 shell 代码。
需要明确的是,我们说这些函数只是编写 shell 代码。它们不会执行它!这需要由 shell 本身完成!这就是为什么我们需要一个 conda
shell 函数,以便这些 shell 字符串可以在会话中被 eval
或 source
。
$ conda shell.bash activate
export PATH='/Users/username/.local/anaconda/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/username/.local/anaconda/condabin:/opt/homebrew/bin:/opt/homebrew/sbin'
unset CONDA_PREFIX_1
PS1='(base) '
export CONDA_PREFIX='/Users/username/.local/anaconda'
export CONDA_SHLVL='1'
export CONDA_DEFAULT_ENV='base'
export CONDA_PROMPT_MODIFIER='(base) '
export CONDA_EXE='/Users/username/.local/anaconda/bin/conda'
export _CE_M=''
export _CE_CONDA=''
export CONDA_PYTHON_EXE='/Users/username/.local/anaconda/bin/python'
让我们看看运行 conda shell.bash activate
会发生什么。
$ eval "$(conda shell.bash activate)"
看到了吗?它只将一些 shell 代码写入标准输出,但没有执行。我们需要这样做才能真正运行它。
这本质上就是 conda activate
的作用:它调用注册的 shell 激活器以获取所需的 shell 代码,然后 eval
它。在某些没有 eval
等效项的 shell 中,会编写并源代码或调用一个临时脚本。最终效果相同。
好吧,但是那个 shell 代码在做什么呢?主要是正确设置您的 PATH
,以便可以找到 base
环境的可执行文件(如 python
)。它还设置了一些额外的变量以保存对当前活动环境路径、shell 提示修饰符和其他 conda
内部信息的引用。
$ conda shell.bash activate mamba-poc
PS1='(mamba-poc) '
export PATH='/Users/username/.local/anaconda/envs/mamba-poc/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/username/.local/anaconda/condabin:/opt/homebrew/bin:/opt/homebrew/sbin'
export CONDA_PREFIX='/Users/username/.local/anaconda/envs/mamba-poc'
export CONDA_SHLVL='2'
export CONDA_DEFAULT_ENV='mamba-poc'
export CONDA_PROMPT_MODIFIER='(mamba-poc) '
export CONDA_EXE='/Users/username/.local/anaconda/bin/conda'
export _CE_M=''
export _CE_CONDA=''
export CONDA_PYTHON_EXE='/Users/username/.local/anaconda/bin/python'
export CONDA_PREFIX_1='/Users/username/.local/anaconda'
此命令还可以生成您想要的任何其他环境的代码,而不仅仅是 base
。只需传递名称或路径。
现在路径不同,一些数字(例如 CONDA_SHLVL
)也不同。conda 使用它来跟踪之前激活的内容,以便在您停用最后一个时,可以无缝地返回到之前的一个。
激活/停用脚本#
$ conda shell.bash activate compilers
PS1='(compilers) '
export PATH='/Users/username/.local/anaconda/envs/compilers/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/username/.local/anaconda/condabin:/opt/homebrew/bin:/opt/homebrew/sbin'
export CONDA_PREFIX='/Users/username/.local/anaconda/envs/compilers'
export CONDA_SHLVL='2'
export CONDA_DEFAULT_ENV='compilers'
export CONDA_PROMPT_MODIFIER='(compilers) '
export CONDA_EXE='/Users/username/.local/anaconda/bin/conda'
export _CE_M=''
export _CE_CONDA=''
export CONDA_PYTHON_EXE='/Users/username/.local/anaconda/bin/python'
export CONDA_PREFIX_1='/Users/username/.local/anaconda'
. "/Users/username/.local/anaconda/envs/compilers/etc/conda/activate.d/activate-gfortran_osx-arm64.sh"
. "/Users/username/.local/anaconda/envs/compilers/etc/conda/activate.d/activate_clang_osx-arm64.sh"
. "/Users/username/.local/anaconda/envs/compilers/etc/conda/activate.d/activate_clangxx_osx-arm64.sh"
激活/停用代码还可以包括对激活/停用脚本的调用。如果存在于您 shell 的适当目录中(例如 CONDA_PREFIX/etc/conda/activate.d/
),它们将分别在停用之前或激活之后被调用。例如,编译器通常设置一些环境变量以帮助配置默认标志。这就是当您激活包含 Clang 和 Gfortran 的环境时发生的情况。
$ conda shell.bash deactivate
export PATH='/Users/username/.local/anaconda/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/username/.local/anaconda/condabin:/opt/homebrew/bin:/opt/homebrew/sbin'
. "/Users/username/.local/anaconda/envs/compilers/etc/conda/deactivate.d/deactivate_clangxx_osx-arm64.sh"
. "/Users/username/.local/anaconda/envs/compilers/etc/conda/deactivate.d/deactivate_clang_osx-arm64.sh"
. "/Users/username/.local/anaconda/envs/compilers/etc/conda/deactivate.d/deactivate-gfortran_osx-arm64.sh"
unset CONDA_PREFIX_1
PS1='(base) '
export CONDA_PREFIX='/Users/username/.local/anaconda'
export CONDA_SHLVL='1'
export CONDA_DEFAULT_ENV='base'
export CONDA_PROMPT_MODIFIER='(base) '
export CONDA_EXE='/Users/username/.local/anaconda/bin/conda'
export _CE_M=''
export _CE_CONDA=''
export CONDA_PYTHON_EXE='/Users/username/.local/anaconda/bin/python'