linux - 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
.
那里发生了什么事?
解决方案
不对称破坏了可逆性
问题是 Conda 也在操纵PATH
变量,并且脚本的运行顺序与正确的逆运算不一致。即,激活和停用的操作顺序是:
- 更新环境变量(包括
PATH
) 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 在激活和停用方面所做的全部,但它涵盖了大部分内容。
推荐阅读
- mysql - MYSQL全文搜索以及少于4个字符的使用什么?
- python - 在 Python 中的同一行上分配多个值是否清楚?
- reactjs - 抽屉导航不出现。实际上出现了一个Cannot call a class as a function
- list - 如何让用户输入 1 到 5 之间的值,其中 1 将返回保存在 python 中列表索引 [0] 中的员工信息
- reactjs - axios在strapi.io中提出编辑用户的请求不起作用
- c - 循环内递归
- javascript - HTML Canvas:更改透明画笔的颜色会导致画布上的所有颜色发生变化
- ruby-on-rails - 为 ruby on rails 设置本地环境时,Postgresql 错误连接到数据库失败
- image-processing - 用于识别文档中的文本是最初存在还是只是合成叠加的图像转换函数
- javascript - 破坏赋值以交换 ES6 中的值