首页 > 解决方案 > Conda activate.d 和 deactivate.d 不符合我的预期

问题描述

我正在尝试通过使用 activate.d 和 deactivate.d 来修改 conda 中的 $PATH 变量,例如:

在激活.d 中:

export OLD_PATH = $PATH
export PATH= "/path/to/something:$PATH"

在 deactivate.d 中:

export PATH = $OLD_PATH
unset OLD_PATH

基础环境中,echo $PATH输出:

(base) $ echo $PATH
/home/myname/anaconda3/bin:/home/myname/anaconda3/condabin:/home/myname/bin:/home/myname/.local/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/cuda-8.0/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/sbin

然后我通过以下方式激活我的环境:

(base) $ conda activate myproject

myproject环境中,echo $PATH输出:

(myproject) $ echo $PATH
/path/to/something:/home/myname/anaconda3/envs/myproject/bin:/home/myname/anaconda3/condabin:/home/myname/bin:/home/myname/.local/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/cuda-8.0/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/sbin

这正是我所期望的。但是,当我尝试通过使用返回基本环境时

(myproject) $ conda deactivate

我期望的是输出与在基本环境echo $PATH中所做的相同的事情。但是,我得到的是:

(base) $ echo $PATH
/home/myname/anaconda3/envs/myproject/bin:/home/myname/anaconda3/condabin:/home/myname/bin:/home/myname/.local/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/cuda-8.0/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/sbin

请注意,第一条路径/home/myname/anaconda3/envs/myproject/bin不是/home/myname/anaconda3/bin.

那里发生了什么事?

标签: linuxanacondaconda

解决方案


不对称破坏了可逆性

问题是 Conda 也在操纵PATH变量,并且脚本的运行顺序与正确的逆运算不一致。即,激活和停用的操作顺序是:

  1. 更新环境变量(包括PATH
  2. etc/conda/(de)activate.d在文件夹中运行脚本。

为了与逆运算一致,需要运算的对称性。也就是说,activate 应该做 (1) 然后 (2),而 deactivate 应该做 (2) 然后 (1)。

相反,发生的情况是OLD_PATH您保存的实际对应于 PATH被操纵以激活 env 之后。

解决方法

OLD_PATH您可以仅跟踪添加的内容并在停用脚本中删除它,而不是尝试捕获。例如,像

激活.d 脚本

export MY_ADDED_PATH="/path/to/something"
export PATH="$MY_ADDED_PATH:$PATH"

deactivate.d 脚本

# Credit for escaping: https://unix.stackexchange.com/a/129063/148899
escaped_lhs=$(printf '%s\n' "$MY_ADDED_PATH:" | sed 's:[][\\/.^$*]:\\&:g')
export PATH=$(echo "$PATH" | sed "s/$escaped_lhs//") 
unset MY_ADDED_PATH

这似乎对我有用 osx-64


调试提示

Conda 处理起来很麻烦,因为它是 shell 函数和 Python 的混合体。然而,其中一件巧妙的事情是 Conda 入口点(例如bin/conda)具有一些返回 shell 命令字符串的内部函数。

具体来说,可以检查在运行命令时将在 shell 中运行的内容conda activate foo,使用

$CONDA_EXE shell.posix activate foo

相似地,

$CONDA_EXE shell.posix deactivate

将列出停用的操作。这并不是 Conda 在激活和停用方面所做的全部,但它涵盖了大部分内容。


推荐阅读