环境隔离

现在很多github上的项目在安装的时候都需要新建一个conda环境,建立环境是方便不同工具的版本隔离,不隔离起来工具之间会乱套。

不隔离狗子要打起来,给狗子一个安静的窝吧!

除了conda环境之外,也有pyenv、docker、虚拟机等等,其实它们都是起到了隔离的作用,隔离的作用范围我理解的大致为:

不同机器>虚拟机>docker>conda环境>pyenv\textbf{不同机器} > \textbf{虚拟机} > \textbf{docker} > \textbf{conda环境} > \textbf{pyenv}

不同机器:可以在硬件上就不同,比如一台用的是A卡,另外一台用的是N卡,这种隔离最彻底。

虚拟机:是除了硬件之外,其他的都使用新的一套系统,和原本的系统之间没有太强的联系;

docker:某种程度上接近虚拟机,但是和原本的系统仍然可以沟通,可以访问资源,它可以隔离不同的CUDA版本(后续会写一篇关于docker搭建和环境构建的博客);

conda环境:只能隔离一些常见的工具包,它是依赖于这个系统下,比如Ubuntu20.04,安装的工具版本也要符合这个系统,可以隔离不同的python、perl、R或者其他的很多工具(非系统级别的工具),它不能隔离CUDA的不同版本

pyenv:主要是隔离了python相关的环境和工具(因为有conda版本管理,用的人不是很多)。

因为深度学习的火热,主要和python相关的conda工具是目前常用的环境管理方式,特别是在python3.8之后和python3.7之前的大的差异,环境的隔离是很有必要的。不方便的就是不同环境下工具调用时需要不断的conda activateconda deactivate。现在打这俩命令我已经形成肌肉记忆,如果用计算机记录我的打字频率,在这个时候绝对是100000APM,其他时候除了ctrl+cctrl+v就没能像这样快的了。

对生信来说环境隔离也很有必要,因为生信工具的开发人员喜好不同或者是之前的系统环境懒得折腾(除非服务器烧掉),有的甚至还在python2.7下编写代码,不用conda环境来管理版本就让人很抓狂。除此之外,还有一个非常好用的工具jupyer lab可以在不同环境下使用。

最近我需要在一个conda环境下的python脚本里面使用subprocess来调用其他conda环境下的工具,按照常规思路行不通。最开始考虑的是进程之间的通信,但是感觉没有那个必要。

1
2
3
import subprocess

subprocess.run(["bash", "-c", "conda activate 环境2"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

这样是不行的。出现错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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'.

在子shell进程下似乎conda没办法直接activate。

准备工作

这是第一篇介绍conda的文章,就把conda安装的步骤写一下。

conda分为anaconda和miniconda3两个类型,miniconda3是anaconda的精简版本,主要功能没有少,就是少了一些模块一些其他软件功能比如spyder啥的,因为后面主要是在子环境下运行,而子环境需要重新装模块,所以只需要用miniconda3就可以,如果有必要再用conda命令装就是了。

使用清华的miniconda3镜像下载:

1
2
3
4
# 找一个比较新的日期的conda版本下载就行,不一定需要最新的版本
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py39_23.9.0-0-Linux-x86_64.sh
# 执行安装
bash Miniconda3-py39_23.9.0-0-Linux-x86_64.sh

直接回车:

1
2
3
4
5
6
Welcome to Miniconda3 py39_23.9.0-0

In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue
>>>

按空格到这里输入yes

1
2
Do you accept the license terms? [yes|no]
[no] >>> yes

直接回车

1
2
3
4
5
6
7
8
9
Miniconda3 will now be installed into this location:
/miniconda3

- Press ENTER to confirm the location
- Press CTRL-C to abort the installation
- Or specify a different location below

[/miniconda3] >>>
PREFIX=/miniconda3

初始化 miniconda,输入 yes

1
2
3
4
installation finished.
Do you wish the installer to initialize Miniconda3
by running conda init? [yes|no]
[no] >>> yes

设置不自动激活base环境:

1
conda config --set auto_activate_base false

到这里主要步骤完成,可以再配置一下下载的源什么的

环境的创建

这里随便创建3个环境用来后面问题的描述

1
2
3
conda create --name 环境1
conda create --name 环境2
conda create --name 环境3

查看目前的环境:

1
2
3
4
5
6
7
8
conda env list

# conda environments:
#
# base * /home/xxx/miniconda3
# 环境1 /home/xxx/miniconda3/envs/环境1
# 环境2 /home/xxx/miniconda3/envs/环境2
# 环境3 /home/xxx/miniconda3/envs/环境3

乱七八糟的环境创建太多,很烦,移除环境命令为:

1
conda remove --name 环境1 --all

bash脚本的conda环境转换

如果你目前位于base环境下,可以使用下面的代码在bash脚本中激活环境:

1
2
3
4
5
6
7
8
9
10
# 执行代码
eval "$(conda shell.bash hook)"
# 激活环境
conda activate 环境1

# 做点什么事情。。。
python tool.py

# 退出环境
conda deactivate

上面的方式不能在已经存在conda的环境下在bash脚本中进行切换。

如果你本来就在conda的环境下,比如在环境1下面,需要在bash中更换为环境2,这样在bash脚本这样写可以切换:

1
2
3
4
5
6
7
8
9
10
11
# 如果是anaconda3就写成:source ~/anaconda3/etc/profile.d/conda.sh
# 直接退回到base环境下
source ~/miniconda3/etc/profile.d/conda.sh
# 激活环境
conda activate 环境2

# 做点什么事情。。。
python tool.py

# 退出环境
conda deactivate

这样就方便使用python的subprocess进行批量的不同环境下的工具的使用。

1
2
3
import subprocess

subprocess.run(["bash", "-c", "source ~/miniconda3/etc/profile.d/conda.sh; conda activate 环境2"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

参考

Python - Activate conda env through shell script

Can’t execute conda activate from bash script

Allow activating multiple environments

图片修改自:

图网