首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >污染环境?

污染环境?
EN

Stack Overflow用户
提问于 2021-09-02 02:05:58
回答 1查看 4.8K关注 0票数 8

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

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

conda init是做什么的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-02 05:40:28

回答策略

conda init命令所做的一切及其后果都是特定于shell的。与其试图涵盖所有案例,不如让我们来看看一个案例,注意到我们可以通过替换他们感兴趣的外壳来复制这一分析。

案例研究:conda init zsh

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

探索命令:模拟运行

许多Conda命令通过--dry-run, -d标志包含某种形式的模拟运行功能,结合详细的标志,可以看到不执行这些命令会做些什么。对于init命令,只需尝试运行就可以告诉我们它将修改哪些文件:

代码语言:javascript
复制
$ 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. <==

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

补丁预览

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

代码语言:javascript
复制
$ 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

也就是说,行动计划是将这16行添加到.zshrc文件中。在这种情况下,我没有一个现有的.zshrc文件,所以它计划将其添加到第1行,如果该文件已经存在,它将追加这些行。

解释Shell代码

让我们先概述一下这段代码,然后再关注细节。本质上,这是尝试设置一些shell功能的冗余序列。它们从大多数到最低功能都是有序的。

康达希望做什么

密码

代码语言:javascript
复制
__conda_setup="$('/Users/mfansler/miniconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"

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

我马上就会更深入地了解这里发生的事情。

回退1:硬编码Shell函数

如果这个奇怪的内部命令失败了,那么devs就会包含一些基本的shell函数(特别是conda activate)的硬编码版本。这包括:

代码语言:javascript
复制
miniconda3/etc/profile.d/conda.sh

他们只需检查文件是否存在并对其进行源。让我们进入最后一个选项,然后我们将返回到查看功能。

退步2:最后的度假村

绝对的最后一种方法是从Condav4.4开始,直接违反常设建议,这就是简单地将环境的bin目录放在PATH上。在这种情况下,没有conda activate功能;这只会确保Conda在您的路径上。

详细信息: Shell功能

回到预期的情况,我们只需获得字符串结果,就可以准确地检查它的计算结果:

代码语言:javascript
复制
$ conda shell.zsh hook

__add_sys_prefix_to_path() {
    # In dev-mode CONDA_EXE is python.exe and on Windows
    # it is in a different relative location to condabin.
    if [ -n "${_CE_CONDA}" ] && [ -n "${WINDIR+x}" ]; then
        SYSP=$(\dirname "${CONDA_EXE}")
    else
        SYSP=$(\dirname "${CONDA_EXE}")
        SYSP=$(\dirname "${SYSP}")
    fi

    if [ -n "${WINDIR+x}" ]; then
        PATH="${SYSP}/bin:${PATH}"
        PATH="${SYSP}/Scripts:${PATH}"
        PATH="${SYSP}/Library/bin:${PATH}"
        PATH="${SYSP}/Library/usr/bin:${PATH}"
        PATH="${SYSP}/Library/mingw-w64/bin:${PATH}"
        PATH="${SYSP}:${PATH}"
    else
        PATH="${SYSP}/bin:${PATH}"
    fi
    \export PATH
}

__conda_exe() (
    __add_sys_prefix_to_path
    "$CONDA_EXE" $_CE_M $_CE_CONDA "$@"
)

__conda_hashr() {
    if [ -n "${ZSH_VERSION:+x}" ]; then
        \rehash
    elif [ -n "${POSH_VERSION:+x}" ]; then
        :  # pass
    else
        \hash -r
    fi
}

__conda_activate() {
    if [ -n "${CONDA_PS1_BACKUP:+x}" ]; then
        # Handle transition from shell activated with conda <= 4.3 to a subsequent activation
        # after conda updated to >= 4.4. See issue #6173.
        PS1="$CONDA_PS1_BACKUP"
        \unset CONDA_PS1_BACKUP
    fi
    \local ask_conda
    ask_conda="$(PS1="${PS1:-}" __conda_exe shell.posix "$@")" || \return
    \eval "$ask_conda"
    __conda_hashr
}

__conda_reactivate() {
    \local ask_conda
    ask_conda="$(PS1="${PS1:-}" __conda_exe shell.posix reactivate)" || \return
    \eval "$ask_conda"
    __conda_hashr
}

conda() {
    \local cmd="${1-__missing__}"
    case "$cmd" in
        activate|deactivate)
            __conda_activate "$@"
            ;;
        install|update|upgrade|remove|uninstall)
            __conda_exe "$@" || \return
            __conda_reactivate
            ;;
        *)
            __conda_exe "$@"
            ;;
    esac
}

if [ -z "${CONDA_SHLVL+x}" ]; then
    \export CONDA_SHLVL=0
    # In dev-mode CONDA_EXE is python.exe and on Windows
    # it is in a different relative location to condabin.
    if [ -n "${_CE_CONDA:+x}" ] && [ -n "${WINDIR+x}" ]; then
        PATH="$(\dirname "$CONDA_EXE")/condabin${PATH:+":${PATH}"}"
    else
        PATH="$(\dirname "$(\dirname "$CONDA_EXE")")/condabin${PATH:+":${PATH}"}"
    fi
    \export PATH

    # We're not allowing PS1 to be unbound. It must at least be set.
    # However, we're not exporting it, which can cause problems when starting a second shell
    # via a first shell (i.e. starting zsh from bash).
    if [ -z "${PS1+x}" ]; then
        PS1=
    fi
fi

conda activate base

我不打算讨论所有这些,但是主要的部分是,它定义了一个名为binconda函数,而不是直接将它放到路径上,而是充当condabin/conda入口点的包装器。这还定义了一个新的功能conda activate,它在幕后使用了一个shell函数__conda_activate()。在最后一步中,它将激活基本环境。

为什么要这样做?

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

Conda“污染环境”吗?

不怎么有意思。可以通过配置设置禁用诸如自动激活和及时修改之类的主要行为功能,这样conda init最终只需将conda activate函数添加到shell中,就可以在环境之间进行干净的切换,而无需手动操作路径。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69023252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档