conda init污染环境?

Gla*_*ery 9 python conda

我在 Pycharm 中设置了一个项目,具有现有的 conda 环境。我的脚本在控制台内运行时可以工作。

我希望能够python -m path_to_my_script/script.py从任何位置运行,但我需要激活 conda。Conda 建议我这样做conda init,但我担心它可能会改变某个地方的设置并破坏东西。

有什么conda init作用?

mer*_*erv 14

回答策略

该命令的具体conda init作用及其后果是特定于 shell 的。让我们不试图涵盖所有案例,而是通过一个案例来说明,在此过程中,人们可以通过替换他们感兴趣的 shell 来复制此分析。


案例分析:conda init zsh

让我们看一下zsh外壳。这是一个常见的 shell(macOS 10.15+ 的默认设置)并且非常接近 bash。另外,我还没有配置它。

探测命令:试运行

许多 Conda 命令通过标志包含某种形式的试运行功能--dry-run, -d,该标志与详细标志相结合,可以在不执行这些操作的情况下查看它会做什么。对于该init命令,单独试运行只会告诉我们它将修改哪些文件

$ conda init -d zsh
no change     /Users/mfansler/miniconda3/condabin/conda
no change     /Users/mfansler/miniconda3/bin/conda
no change     /Users/mfansler/miniconda3/bin/conda-env
no change     /Users/mfansler/miniconda3/bin/activate
no change     /Users/mfansler/miniconda3/bin/deactivate
no change     /Users/mfansler/miniconda3/etc/profile.d/conda.sh
no change     /Users/mfansler/miniconda3/etc/fish/conf.d/conda.fish
no change     /Users/mfansler/miniconda3/shell/condabin/Conda.psm1
no change     /Users/mfansler/miniconda3/shell/condabin/conda-hook.ps1
no change     /Users/mfansler/miniconda3/lib/python3.7/site-packages/xontrib/conda.xsh
no change     /Users/mfansler/miniconda3/etc/profile.d/conda.csh
modified      /Users/mfansler/.zshrc

==> For changes to take effect, close and re-open your current shell. <==
Run Code Online (Sandbox Code Playgroud)

在这里我们可以看到它计划针对 zsh 的用户级资源文件,/Users/mfansler/.zshrc但它没有告诉我们它将如何修改它。还有,天啊!这里的用户体验很糟糕,因为它根本没有反映我使用该标志的事实-d。但不用担心:只要-d旗帜在那里,它实际上就不会改变事情。

补丁预览

-v要查看它到底会做什么,请向命令添加一个详细标志 ( )。这将提供之前输出的所有内容,但现在将向我们显示它将用于修补(更新)文件的差异.zshrc

$ conda init -dv zsh

/Users/mfansler/.zshrc
--- 

+++ 

@@ -0,0 +1,16 @@

+
+# >>> conda initialize >>>
+# !! Contents within this block are managed by 'conda init' !!
+__conda_setup="$('/Users/mfansler/miniconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
+if [ $? -eq 0 ]; then
+    eval "$__conda_setup"
+else
+    if [ -f "/Users/mfansler/miniconda3/etc/profile.d/conda.sh" ]; then
+        . "/Users/mfansler/miniconda3/etc/profile.d/conda.sh"
+    else
+        export PATH="/Users/mfansler/miniconda3/bin:$PATH"
+    fi
+fi
+unset __conda_setup
+# <<< conda initialize <<<
+

# ...the rest is exactly as above
Run Code Online (Sandbox Code Playgroud)

也就是说,行动计划是将这 16 行添加到文件中.zshrc。在本例中,我没有现有.zshrc文件,因此计划将其添加到第 1 行。如果文件已经存在,它将附加这些行。


解释 Shell 代码

在关注细节之前,让我们先概述一下这段代码。本质上,这是设置某些 shell 功能的冗余尝试序列。它们按照功能从最多到最少的顺序排列。

康达希望做什么

代码

__conda_setup="$('/Users/mfansler/miniconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
Run Code Online (Sandbox Code Playgroud)

从自身获取一些内容conda,将结果存储到字符串中,然后如果命令干净退出 ( $? -eq 0),则评估该字符串。这里巧妙的工程是子进程(技术上python -m conda)传回可以在当前进程()中运行的结果zsh,从而允许它定义 shell 函数。

我稍后会更深入地了解这里发生的事情。

回退 1:硬编码 Shell 函数

如果那个奇怪的内部命令失败,开发人员会提供一些基本 shell 函数(特别是 )的硬编码版本conda activate。这是在:

miniconda3/etc/profile.d/conda.sh
Run Code Online (Sandbox Code Playgroud)

他们只需检查文件是否存在并获取它。让我们点击最后一个选项,然后我们将回过头来看看其功能。

后备 2:最后的手段

绝对的最后手段是从字面上违反自 Conda v4.4 以来的长期建议,即简单地将基本环境的bin目录放在PATH. 在这种情况下,没有任何conda activate功能;这只能确保 Conda 在您的 PATH 上。


详细信息:外壳功能

回到预期的情况,我们可以通过简单地获取该字符串结果来准确检查它将评估什么:

__conda_setup="$('/Users/mfansler/miniconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
Run Code Online (Sandbox Code Playgroud)

我不会详细介绍所有这些,但主要部分是,bin它不是直接放在 PATH 上,而是定义了一个名为 的 shell 函数conda,它充当condabin/conda入口点的包装器。这还定义了一个新功能,它在幕后conda activate使用 shell 函数。__conda_activate()在最后一步,它会激活基础环境。

为什么要这样做呢?

这样设计是为了响应配置设置。配置选项auto_activate_basechange_ps1影响 Conda 操作 shell 的方式,从而改变 Conda 在其 shell 函数中包含的功能。


康达“污染环境”吗?

并不真地。可以通过配置设置禁用自动激活和提示修改等主要行为,因此conda init最终只需将conda activate功能添加到 shell 中,即可在环境之间进行干净的切换,而无需手动操作 PATH。

  • 杰出的。谢谢你的详细解释 (3认同)