Python-通过 shell 脚本激活 conda env

我希望运行一个简单的 shell 脚本来简化一些 conda 环境的管理。通过 linux os 中的 conda activate激活 conda 环境在 shell 中工作良好,但在 shell 脚本中存在问题。谁能告诉我为什么会这样?

重复这个问题的例子:

# default conda env
$ conda info | egrep "conda version|active environment"
active environment : base
conda version : 4.6.9


# activate new env to prove that it works
$ conda activate scratch
$ conda info | egrep "conda version|active environment"
active environment : scratch
conda version : 4.6.9


# revert back to my original conda env
$ conda activate base


$ cat shell_script.sh
#!/bin/bash
conda activate scratch


# run shell script - this will produce an error even though it succeeded above
$ ./shell_script.sh


CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'.
To initialize your shell, run


$ conda init <SHELL_NAME>


Currently supported shells are:
- bash
- fish
- tcsh
- xonsh
- zsh
- powershell


See 'conda init --help' for more information and options.


IMPORTANT: You may need to close and restart your shell after running 'conda init'.
159803 次浏览

错误消息相当有用——它告诉您,conda 没有从运行脚本的 subshell 中正确设置。为了能够在脚本中使用 conda,您将需要(如错误消息所说)首先运行 conda init bash(或不管您的 shell 是什么)。Conda 的行为以及如何设置它取决于你的 conda 版本,但是版本4.4 + 行为的原因是 conda依赖于某些环境变量,这些环境变量通常是由 conda shell 本身设置的。最重要的是,这个变更日志条目解释了为什么 conda activatedeactivate命令的行为不再像4.4及以上版本所期望的那样。

有关这方面的更多讨论,请参见 GitHub 上的 官方保密协议


编辑: 更多的研究告诉我,错误消息中提到的 conda init函数实际上是一个新的 v4.6.0特性,它允许快速设置环境,这样您就可以使用 conda activate而不是旧的 source activate。然而,这样做的原因是它添加/更改了当前 shell 的几个环境变量,并且还对 RC 文件进行了更改(例如: .bashrc) ,而 RC 文件的更改从来不会在当前 shell 中被检测到——只会在新创建的 shell 中被检测到。(当然,除非你来源。又是巴希尔)。事实上,conda init --help就是这么说的:

重要: 在运行 conda init之后,大多数 shell 将需要关闭并重新启动以使更改生效

但是,您显然已经运行了 conda init,因为您的 能够交互式地使用 conda activate。事实上,如果你打开你的。Bashrc,您应该能够看到由 conda 添加的一些代码行,这些代码行告诉您的 shell 在哪里查找 conda 命令。但是,脚本的问题在于。Bashrc 是由运行 shell 脚本的子 shell 提供的 没有(更多信息参见 这个答案)。这意味着即使您的非登录交互式 shell 看到了 conda 命令,您的非交互式脚本 subshell 也不会看到——无论您调用 conda init多少次。

这导致了一个猜想(我自己没有 Linux 上的 conda,所以我不能测试它) ,通过这样运行你的脚本:

bash -i shell_script.sh

你应该看到 conda activate正常工作。为什么?-i是一个 bash 标志,它告诉 shell 您开始以交互模式运行,这意味着它将自动为您提供源代码。巴希尔。这应该足以使您能够在脚本中使用 conda,就像您正常使用它一样。

我使用‘ source command’来运行 shell 脚本,它可以工作:

source shell_script.sh

bash的快速解决方案: 将下面的 init 脚本转换为 Bash 脚本。

eval "$(command conda 'shell.bash' 'hook' 2> /dev/null)"

成交。


对于其他 shell,请检查 shell 的 init conf,在 shell conf 中复制以下内容,并将其预置到脚本中。

# >>> conda initialize >>>
...
# <<< conda initialize <<<

你也可以用

conda init --all --dry-run --verbose

以获取脚本中所需的 init 脚本。

解释

这与 conda4.6中引入 conda init有关。

引自 Conda 4.6发布日志

Conda 4.4允许“ Conda 激活 envname”。问题是设置 shell 来使用这个新特性并不总是那么简单。Conda 4.6添加了广泛的初始化支持,因此比以往任何时候都多的 shell 可以使用新的“ Conda active”命令。有关更多信息,请阅读“ conda init-help”的输出

conda4.6中引入 conda init之后,conda 只暴露命令 将 conda转换为 PATH,但不是所有来自“基”的二进制文件。环境交换机由 conda activate env-nameconda deactivate在所有平台上统一。

但是要使这些新命令工作,您必须使用 conda init进行额外的初始化。

问题是脚本文件在子 shell 中运行,而 conda没有在这个子 shell 中初始化。

参考文献

在 shell 中简单地执行这样的操作有什么问题:

Source/opt/conda/etc/profile.d/conda.sh

(conda init 仍然被标记为实验,因此不确定使用它是否是一个好主意)。

在 shell 脚本中使用 conda activatesource activate并不总是有效,可能会抛出这样的错误。在脚本中将 source ~/miniconda3/etc/profile.d/conda.sh置于任何 conda activate命令之上是一个简单的工作:

source ~/miniconda3/etc/profile.d/conda.sh # Or path to where your conda is
conda activate some-conda-environment

这是一个对我有效的解决方案,如果共享脚本,它也会起作用。这也避免了必须使用 conda init,因为在一些集群上,我使用的系统已经初始化,但是 conda activate仍然不能在 shell 脚本中工作。

在尝试从 C + + 或 Python 文件激活 conda env 时,我也出现了完全相同的错误。我通过绕过 conda 激活语句并使用特定 conda env 的绝对路径解决了这个问题。

对我来说,我使用 conda 设置了一个名为“ testenv”的环境。

我搜索了所有的 Python 环境

whereis python | grep 'miniconda'

它返回了一个 python 环境列表,然后我使用以下命令运行 my _ python _ file.py。

~/miniconda3/envs/testenv/bin/python3.8 my_python_file.py

您也可以在 windows 上做同样的事情,但是查找 python 和 conda python 环境是有点不同的。

如果希望使用 shell 脚本在另一个 conda env 中运行另一个 python 文件,只需通过以下命令运行另一个文件。

os.system('conda run -n <env_name> python <path_to_other_script>')
   #open terminal or CMD as administrator


$ cd <path Anaconda3 install>\Scripts


$ activate


$ cd ..


$ conda activate scratch

这个答案类似于@Lamma 的答案

(1)定义了多个变量,其中 conda 激活函数、环境目录和环境

conda_activate=~/anaconda3/bin/activate
conda_envs_dir=~/anaconda3/envs
conda_env=<env name>

(2)利用环境来源 conda activate

source ${conda_activate} ${conda_envs_dir}/${conda_env}

(3)然后你可以运行你的 Python 脚本

python <path to script.py>

这绕过了 conda init的要求。我的 .bashrc已经被初始化和源的 .bashrc文件不适合我。@ 南丫岛的回答对我和上面的代码都有效。

我只是遵循了类似于 洪旭的解决方案

因此,要运行一个 shell 命令,该命令使用参数和特定的 conda 环境调用该脚本:

来自木星的细胞,是这样的:

p1 = <some-value>
run = f"conda run -n {<env-name>} python {<script-name>.py} \
--parameter_1={p1}"


!{run}

我没有发现以上任何脚本有用。如果你想在非交互模式下运行 conda,这些都可以,但是我想在交互模式下运行它。如果我逃跑:

conda activate my_environment

在 bash 脚本中,它只在脚本中运行。

我发现在。Bashrc 是将目录更改为我正在处理的特定项目并为我设置正确的 conda 环境所需的全部内容。所以我加入了。巴希尔:

alias my_environment="cd ~/subdirectory/my_project && conda activate my_environment"

然后:

source ~/.bashrc

然后我就可以在命令行输入:

my_environment

改变到正确的项目和正确的环境,每次我想工作在一个不同的项目。

$ conda activate scratch

或者

$ source activate scratch

这个来自 Github的答案对我很有用(我在使用 Ubuntu,所以它不仅仅适用于 Windows) :

eval "$(conda shell.bash hook)"
conda activate my_env

问题是,当您运行 bash 脚本时,会创建一个新的(linux) shell 环境,这个环境没有被正确地初始化。如果您的目的是激活一个 conda 环境,然后通过脚本运行 python,那么您可以正确地初始化创建的 shell 在可接受的解决方案中讨论的环境。

然而,如果您想要 在您完成这个脚本之后激活 conda 环境,那么这将无法工作,因为 conda 环境已经在新的 shell 上发生了更改,并且当您完成脚本时将退出该 shell。可以把这看作是运行 bash,然后运行 conda activate...,然后运行出口退出 bash... ... 在 如何在 Linux 上执行当前 shell 中的脚本?中的更多细节:

DR :

  1. 添加行 #!/bin/bash作为脚本的 第一句台词
  2. 键入命令 source shell_script.sh. shell_script.sh

注意: bash 中的 .等价于 bash 中的 source