介绍
本篇介绍如何让linux在不激活任何环境时,调用python命令直接使用到conda的某个子环境。
首先说明本篇文章的工作原由,以及踩过的坑。
在之前的工作中,一般进行python开发都会使用conda进行包管理,以达到隔离多个环境的目的。例如:
- 同时创建python2和python3环境(一些旧代码和旧工具会使用python2开发,而新的代码一般采用python3)
- 同时创建python3.6和python3.7环境(TensorFlow的低版本支持python3.5或3.6,而其他工具可以支持python3.7)
- 同时创建numpy1.14和numpy1.16环境(某些更高级的库只支持低版本的工具,另一些支持高的)
在这些环境隔离的任务中,conda完成的很好。唯一麻烦的地方在于每次都需要使用命令conda activate {env_name}
来激活不同的环境。
问题来了,在一些场景中,外部程序需要调用服务器上的api,又无法做出conda activate
的命令,命令是直接使用python xxx.py
,这时候只能使用linux自带的python命令,或者conda的base环境的python命令。所以需要将环境搭建在linux的python或者conda的base。搭建过程中,遇到的问题来自两个方面:
- linux自带的python在搭建深度学习环境(tf-gpu、opencv、scikit、scipy等)时,tf-gpu装成功了,但是在实际调用的时候,无法成功调到gpu,程序还是使用cpu在跑,同时报了找不到共享库(libxxx.so.10.0之类)的错误(或者warning,因为没有停止运行)。而在用conda的时候,安装tf-gpu是可以正常跑通的,所以可以基本确认,NVIDIA、cuda、cudnn安装应该没有问题。(这里有可能是cuda版本和原生pip不匹配的问题,cuda用的是10.1,而非10.0,这里没有用10.0试,所以不知道更换到10.0会不会解决这个问题。但是conda的tf-gpu是可以用cuda 10.1跑的)
- 将tf直接安装到conda的base环境中时,首先会将一些旧包升级(例如numpy,例如certificate证书),而这个升级的过程是先删除旧的,再装新的。删除的这一步时,conda会将它本身一些底层依赖也删掉,最终结果就是conda崩了,报错为
No module named 'conda
,这时候先把旧的anaconda删了,然后重新安装Anaconda即可解决,之前旧的库就都没了。
所以以上两个思路:将环境搭建在linux默认的python或者conda的base 是不行的。
解决方法
解决方法:将linux默认的python做软链接,链接到conda的子环境。
conda创建子环境
创建环境:conda create -n child_env python=3.6
切换环境:conda activate child_env
安装pytorch:conda install pytorch torchvision cudatoolkit=10.0
安装tensorflow:conda install tensorflow-gpu
安装其他包:conda install xxx,xxx,...
制作软链接
先将老的链接备份:mv /usr/bin/python /usr/bin/python22
再做链接:ln -s /root/anaconda3/envs/child_env/bin/python3 /usr/bin/python
第一个路径需要改成自己的anaconda路径,child_env改成自己的环境名,第二个路径不用改。
测试
先关掉conda环境:conda deactivate
再运行:python xxx.py
缺陷
用这个方法,虽然解决了直接调用python命令的问题。但是引入了新的问题。
- 首先要在.bashrc里去掉anaconda的默认激活,否则python调的是conda的base,而不是child_env
- python可以软链接,但是我做pip软链接时
ln -s /root/anaconda3/envs/child_env/bin/pip /usr/bin/pip
,pip list无法直接显示child_env的环境,判定是失败了。 - 所以如果需要装包的时候,要把.bashrc的conda先激活:取消export的注释,source .bashrc,conda activate child_env,conda install。然后再注释.bashrc的anaconda,source .bashrc。