1. 先从一场环境灾难说起
做深度学习实验的人,十有八九都经历过这种崩溃瞬间:上个月用某框架跑通的项目,这个月打开突然报ImportError,一查发现是依赖包版本被其他项目悄悄"升级"了;或者新拉下来的代码要求Python 3.10,但你的机器上还倔强地躺着3.6。我曾经有次赶实验进度,三个项目挤在一个环境里,装A项目的新版依赖时把B项目的基础库顶掉了,结果B项目第二天要跑实验直接崩掉,硬是花了两天排查加重装才救回来。
从那之后,"虚拟环境"四个字就刻在我脑子里了。说白了,虚拟环境就是给每个项目单独隔出来的一块小天地,里面有独立的Python解释器、独立的依赖包目录,项目之间互不干扰。你做深度学习实验,不同的论文复现经常需要不同框架版本,比如一个项目要TensorFlow 1.x,另一个要TensorFlow 2.x,要是都装在同一个环境里,冲突几乎是必然的。虚拟环境就是来解决这个痛点的,也是所有深度学习实验开始前必须做好的基础功课。
这篇文章我把自己实际用下来的完整流程写清楚,覆盖创建、查看、删除三个核心操作,同时会详细解释每一步背后的逻辑和踩坑经验。不论你是刚入门深度学习的新手,还是被环境依赖折磨过的"老伤员",看完之后应该都能建立一套干净、可控的实验环境管理习惯。
2. 选对工具:conda与venv怎么选
2.1 两个工具的核心差别
管理Python虚拟环境,主流方案就两个:conda 和 venv。很多人一开始搞不清楚这俩啥区别,其实定位完全不同。
venv是Python官方自带的一个模块(从Python 3.3开始内置),它创建的是"轻量级"虚拟环境,复用它当前那套Python基础解释器,把依赖包装在一个独立目录里。优点是轻巧、不需要额外安装工具,缺点也很明显:它只管Python的包,管不了Python版本本身。如果你需要同时跑Python 3.6和3.10的代码,venv就有点力不从心了,因为你的机器上得先装好对应版本的Python解释器。
conda就属于"重武器"了,它不光是个虚拟环境工具,更是个通用的包管理和环境管理系统(跨语言、跨平台)。conda可以指定创建任意Python版本的虚拟环境,比如直接conda create -n py36 python=3.6,它会自动帮你下载对应版本的Python解释器放到环境里,完全不用你手动装。这对深度学习实验特别实用,因为很多老代码、旧框架官方只支持特定Python版本。
2.2 我为什么倾向推荐conda
个人习惯是用conda来管深度学习环境,用venv处理一些轻量级的小脚本。原因有这么几个:
第一,深度学习框架(尤其是一些老版本)跟Python版本绑定得很死。比如某个经典代码库要求Python 3.7和某框架1.14,你用conda可以一秒钟创建出一个完全独立的Python 3.7环境,而venv就得先折腾系统全局Python版本,风险高、容易把系统环境搞乱。
第二,conda的依赖解析能力更强。安装PyTorch这套东西的时候,GPU版CUDA依赖链非常复杂,conda能帮你自动处理好多底层库的依赖关系。有些包通过pip装会出各种诡异问题,换conda就好好的。
第三,conda环境管理命令非常统一,创建、查看、导出、删除都有对应命令,比手动管理目录结构省心得多。尤其是环境导出成yaml文件,换台机器一键重建,这个体验是venv比不了的。
当然,conda也不是没有缺点:体积大,环境创建的初始开销高,conda install在某些情况下解析包会慢,而且有些冷门包只有pip版本。所以更合理的做法是:conda管"大环境"(比如Python版本、CUDA、主要框架),pip管"细节包"(比如一些GitHub上才有的冷门库),两者混着用。这个组合拳我用很久了,效果很稳。
注意:无论用哪个工具,核心原则是一样的——每个深度学习项目一个独立虚拟环境,环境之间绝不共享依赖。
3. 创建虚拟环境:两种流派的操作细节
3.1 conda环境下创建一个深度学习环境
第一步当然是装conda,这个就不展开说了。装完之后,我把创建conda环境的标准命令列一下:
conda create -n deepenv python=3.8 # 创建环境的同时直接安装常用包 conda create -n deepenv python=3.8 numpy scipy matplotlib jupyter常用参数里,-n后面跟的是环境名字,你可以理解成给这个虚拟环境起的唯一ID。python=3.8用来指定这个环境里的Python版本。这里控制好Python版本等于直接决定了环境的上限——很多框架对Python版本有硬性要求,在创建阶段就锁定是最稳妥的。
我在深度学习实验里通常会加一个步骤:先创建环境,再装深度学习框架。比如:
conda create -n pytorch_env python=3.8 conda activate pytorch_env # 然后再根据你的CUDA版本选择合适的安装命令 pip install torch==1.8.0 torchvision torchaudio为什么不创建的时候一口气全装掉?因为框架的安装命令经常要参考官方文档做调整,特别是GPU版本,涉及CUDA对应关系。分两步走,万一装错了重来也比较省事。
另外,conda有个很实用的配置可以提升创建速度——让conda优先使用国内镜像源。有的镜像源访问速度不稳定,换成国内源之后快很多,这里不展开具体配了,操作也不算复杂。
3.2 venv环境下创建独立空间
如果你的场景比较简单——系统Python版本正好满足项目要求,直接用venv就够了:
# 在项目目录下创建虚拟环境,环境名为venv python -m venv venv # 如果你想指定使用某个特定版本的Python来创建 python3.8 -m venv venv这个命令会在当前目录下生成一个venv文件夹,里面包含bin(Windows下是Scripts)、lib、include等子目录。看到这个文件夹结构大致就明白原理了:这块区域就是这个项目的"独立空间",后续安装的包都会放到lib/pythonX.X/site-packages里。
venv创建完成后,激活方式是:
# Linux/macOS source venv/bin/activate # Windows PowerShell venv\Scripts\Activate.ps1 # Windows CMD venv\Scripts\activate.bat激活成功后,命令提示符前面会出现(venv)前缀,说明你已经进入这个独立空间了。之后随便pip install装东西,都会只装到这个环境里,系统全局Python一点不受影响。
3.3 从配置文件快速重建环境
深度学习项目通常需要团队协作或换机器复现,光靠手动一条条输入安装命令太容易漏了。我每次项目定型以后,都会把环境依赖导出成配置文件,别人拿到后一条命令就能把环境完整复原。
conda环境的导出和重建:
# 导出环境配置(包含所有包与版本) conda env export > environment.yaml # 在另一台机器上从配置恢复环境 conda env create -f environment.yamlvenv环境的导出和重建则稍微麻烦点:
# 导出pip freeze列表 pip freeze > requirements.txt # 在新环境中批量安装 pip install -r requirements.txt这个习惯非常重要,我强烈建议所有做实验的人都养成这个习惯。你会发现,过几个月再回头看自己的项目,只需要一行conda env create -f environment.yaml,之前的环境就原封不动地回来了,省去无数重复劳动。
3.4 激活环境后还需要确认什么
很多人激活完环境就以为万事大吉,直接开始装包。其实激活只是第一步,我建议立刻做一件事:确认自己真正在目标环境里。
# 查看当前使用的python路径,确认指向你的环境目录 which python # 查看当前pip对应的环境 which pip # 查看环境内已安装的包 pip listwhich python输出的路径应该是类似/home/yourname/conda/envs/deepenv/bin/python这种,或者venv目录下的bin/python。如果显示的是/usr/bin/python这种系统路径,说明你没有激活成功,或者激活后又跑到了别的地方。这种小检查在深度学习实验调试时能帮你节省无数排查时间,很多"包明明装了却import不了"的诡异问题,十有八九就是环境没对上。
4. 查看虚拟环境:不仅要会建,还要会看
4.1 conda环境管理查询指令
管理多少个环境以后,经常会忘记自己到底建了哪些环境,每个环境里装了些啥。别慌,conda提供了特别直观的查看方式:
# 列出所有环境 conda env list # 或者用conda info --envs,效果类似 conda info --envs输出会分成两列,第一列是环境名称,第二列是这个环境所在的文件路径。路径前带*号的就是当前激活的环境。我还额外记一下每个环境各自装了什么,可以用:
# 列出当前激活环境中的包 conda list # 列出某个指定环境中的包(即使没激活也能看) conda list -n pytorch_envconda list -n 环境名这个用法很实用,比如我想确认某个旧实验环境的PyTorch版本到底是多少,不用切换环境,一条命令直接看。
4.2 查看venv环境的两种方式
venv不像conda那样有一个统一的环境清单数据库。每一个venv就是项目目录下那个普通的文件夹,环境名等同于文件夹的名字。查看方式相对"直白"一些:
- 直接看你的项目目录结构,所有以venv(或你起的其他名字)命名的文件夹,都是一个独立的虚拟环境。
- 在shell里执行
source venv/bin/activate然后看命令行前缀的变化,也能帮你判断到底激活的是哪个。 - 通过
which python看解释器路径,也是一个很可靠的验证方式。
venv的好处是干净、无中央数据库、删环境就是删文件夹;坏处是如果你管理几十个项目,没记录的话很难快速了解全局。我自己的做法:把所有项目的虚拟环境统一放在每个项目根目录里,起名都叫venv,这样一看目录就知道哪些项目有独立环境。
4.3 深度检查当前环境的状态
除了列表查看,有时候还需要深入检查环境内部的软件状态。我在深度学习实验中几乎每天都会用到的排查命令:
# 检查python版本 python --version # 检查pip对应关系(防止装错环境) pip --version # 查看某个包是否已安装及其版本 pip show torch # 列出所有包的简要信息 pip list --format=columns这里面的隐藏坑在于:pip --version能看到这个pip具体属于哪个环境。如果输出末尾有/home/xxx/venv/lib/python3.8/site-packages/pip这样的路径,就说明pip是从当前环境的site-packages里调用的,比较正常。要是pip来自系统路径,那你后面pip install装的所有包都会落在系统环境里,而Python解释器用的却是虚拟环境,这个"错位"会让你debug到怀疑人生。
4.4 我这个"环境状态速查"脚本
因为查看环境状态太频繁,我写了个简单快捷的方式,就是在shell配置里面加几个简短的alias。实际操作中我经常用这种组合:
# 在bashrc或zshrc中配置 alias envs='conda env list' alias cur_env='echo "Python: $(which python)"; echo "Pip: $(which pip)"; python --version' alias torchv='python -c "import torch; print(torch.__version__, torch.cuda.is_available())"'torchv这个alias对深度学习实验特别有用,一条命令确认PyTorch版本和CUDA是否可用。你甚至可以再加一条命令,打印出torch.backends.cudnn.version()来确认cuDNN版本。环境理清楚了,实验的可复现性就有了基础保证。
5. 删除虚拟环境:干净利落的清理艺术
5.1 conda环境删除与防呆操作
环境越建越多,硬盘空间越来越紧,删除一些废弃环境是必须的。conda删除环境命令很简单:
# 删除名为pytorch_env的环境 conda remove -n pytorch_env --all这里要特别注意,--all这个参数一定别漏。如果只写conda remove -n pytorch_env,默认删的是这个环境里的某些包,不是整个环境。带上--all才是真正把整个虚拟环境连根拔起。
删除环境前我会先确认一下,尤其是一些很久没用的环境,万一里面有实验结果或重要代码,删错就麻烦了。不过有一点放心的是,conda环境里通常只装依赖包,项目代码一般不会放在环境目录里,所以删环境基本不影响你的代码。但为了保险,我还是建议动手前用conda env list快速看一眼,确认名字没敲错。
注意:一个隐含的坑是——别删掉
base环境。base环境是conda自带的根环境,删除或者搞乱它会导致整个conda无法使用。好多新手一开始就在base里乱装,最后依赖冲突了想"删掉base重来",这个操作风险很高,我反而不建议这么做。更好的办法是,base环境保持清爽,只装conda自身和管理工具,所有项目环境都单独创建。
5.2 venv环境删除与磁盘清理
venv环境的删除更简单,因为venv本质就是一个目录,直接删目录即可:
rm -rf venvWindows下用资源管理器直接删除那个venv文件夹,或者命令行执行:
rmdir /s /q venv删完之后这个虚拟环境就不存在了,干净利落。但要意识到,venv环境创建时如果复用的Python包比较大,删除后磁盘空间未必立刻释放——有时候还需要手动清理下pip的缓存目录,比如Linux下的~/.cache/pip,不然你会发现空间没多出来多少。
另外提一个我踩过的坑:如果项目里用到IDE(比如集成开发环境),删除venv后,可能需要去IDE配置里把解释器路径改回来,不然IDE会一直报告找不到解释器。这个不复杂,但容易被人忽略。
5.3 删除后如何检查是否删干净
删除环境之后,我通常还会做两道"复查":
# 1. 确认环境列表里已经没有名字了 conda env list # 2. 检查环境目录是否还存在(正常应该不存在) ls /home/yourname/conda/envs/对于venv,则是看项目的目录结构里venv文件夹是否已经没了。其实还有个容易被忽略的检查点——shell激活脚本。如果你曾经在shell配置(.bashrc)里写入了conda activate某个环境的语句,删除环境后这个配置可能会报错,需要同步清理。
5.4 我的环境清理周期与存储策略
虚拟环境管理不只是创建和删除的操作问题,还是一个存储和规划问题。我在用了很长时间之后,总结了一套自己的清理策略:
- 实验进行中的环境:保留着,每天或者每周更新依赖。
- 论文复现完成且确认结果的环境:导出配置文件后,环境本身先留着,等论文成果整理后再定是否删除。
- 不再使用且导出配置备份完的环境:直接删除,节省空间。
另外,深度学习环境的体积往往很大(PyTorch+CUDA动辄几个GB),所以我会定期查看各环境大小,再结合重要性决定去留。查看环境目录大小:
du -sh ~/conda/envs/*管理环境跟管理衣柜一样,定期"断舍离"能让你在需要时更快找到顺手的"衣服"。别等到硬盘满了再临时抱佛脚。
6. 常见问题与排查实录
6.1 环境激活了,怎么import还是系统版本
这是后台私信被问过最多的问题。明明conda activate之后显示前缀变成(deepenv)了,但python进入交互式命令行后,import torch却报找不到,或者torch.__version__还是旧版本。
排查步骤:
# 第一步:确认当前解释器路径 which python # 第二步:确认当前python的搜索路径 python -c "import sys; print(sys.path)"我遇到过一种情况:shell里虽然显示(deepenv)前缀,但which python依然指向/usr/bin/python。原因是conda init没有正确配置shell的初始化脚本,或者某些第三方工具(比如IDE自带的终端)没有加载conda hook。解决办法是重新执行conda init bash(这里要和你的shell类型对应),重启终端再试。
如果是Jupyter Notebook里import不到环境包,常见原因是Jupyter服务是用系统Python启动的,跟你的conda环境是两条线。可以在conda环境里安装ipykernel并添加内核:
conda activate deepenv pip install ipykernel python -m ipykernel install --user --name deepenv --display-name "Python (deepenv)"之后再打开Jupyter Notebook,新建的时候选择名为"Python (deepenv)"的内核就对了。
6.2 conda install太慢怎么办
深度学习环境动辄需要装几十个包,TA的conda源如果不稳定,跑起来折磨人。我最快的一次"翻车"是创建一个环境等了二十分钟还在解决依赖。
后来学乖了,优先做两件事:第一,创建环境时精简依赖——conda create只锁定Python版本和个别核心库,其余包全部留到激活后用pip装;第二,用国内镜像源或者conda自带的Mamba替代方案,mamba在解析依赖上的速度提升非常明显。
# 用mamba替代conda创建环境 mamba create -n deepenv python=3.8这个命令在装大型依赖时体验差异特别明显,比如装PyTorch全家桶,conda install可能要反复求解依赖十来分钟,mamba通常几十秒内搞定。
6.3 环境列表里看不到某个环境
有时你明明记得建过一个名为test_env的环境,但conda env list里死活找不到。这背后通常有两个原因:
- 环境在建到一半时被中断(比如终端突然关闭),导致
envs目录里留下了残留文件,但conda的记录文件里没有完整条目。 - 你手动把环境目录移动过,或者用软链接方式创建过环境,conda没有识别到。
处理方法:
# 查看envs目录下实际有哪些文件夹 ls ~/conda/envs/ # 如果有残留文件夹,确认无用后清理 rm -rf ~/conda/envs/test_env更常碰到的情况发生在venv上。项目换台电脑后,代码仓库同步过来了但venv文件夹没同步(它本来就不该被版本控制追踪),代码一跑就报No module named。解决方案很简单:创建新的venv环境,然后用requirements.txt重装依赖。准备依赖配置这个习惯越是早养成,越是受益无穷。
6.4 环境大小太大,如何瘦身
深度学习环境膨胀是必然的,装了几个大框架之后,环境体积轻松上10GB。我做过几次"环境瘦身",有几个可行方向:
一是清除conda的缓存文件:
conda clean --all二是清理pip缓存:
pip cache purge三是在创建环境时就尽量减少不必要的依赖。很多人创建环境时习惯性补一句conda create -n xxx python=3.8 pandas numpy scipy matplotlib,一次装一堆,其实很多根本用不上。按需安装才是瘦身的最佳方式。
6.5 一个问题速查表
把经常碰到的问题整理成一张表,方便对照排查:
| 现象 | 可能原因 | 处理命令或办法 |
|---|---|---|
| 激活环境后import包失败 | 解释器与pip不匹配,或环境未真正激活 | which python、pip --version |
| conda安装依赖缓慢 | 默认源慢或依赖解析复杂 | 配置国内源、用mamba加速 |
| 环境列表找不到环境 | 环境创建中断或目录被移动 | 查看envs目录残留、重建环境 |
| Jupyter无法使用环境 | 内核未注册 | python -m ipykernel install --user --name env名 |
| 删除环境但空间未释放 | pip/conda缓存仍存在 | conda clean --all、pip cache purge |
命令提示符前缀无法显示(env) | conda init未配置 | 对应shell执行conda init后重开终端 |
7. 养成环境管理习惯:我的标准动作
7.1 一个新实验开始前的三件事
到目前为止,每打开一个深度学习实验项目,我基本都遵循同一套流程,简单可靠:
第一步,创建独立环境并激活:
conda create -n exp_xx python=3.8 conda activate exp_xx第二步,安装框架和基础依赖:
pip install torch torchvision torchaudio pip install numpy scipy matplotlib jupyter第三步,验证环境是"通"的:
python -c "import torch; print(torch.__version__, torch.cuda.is_available())"这三步走完,心里就踏实了。后面的实验就是在这个干净环境里做,不担心跟其他项目互相污染。
7.2 安装依赖时坚持"先写文件,再装环境"
我见过不少同学把实验环境搞得一塌糊涂,根源在于"想到什么装什么"。前一次操作装了个包,后一次操作又把它卸了,环境里堆满了不明不白的库,最后项目代码都不知道在依赖啥。
我现在的新项目都坚持"依赖文件先行"原则:项目一开始就维护一个requirements.txt或environment.yaml,每装一个新的包,就同步把它写进文件里,同时固定版本号。这样不管过多久,环境都能稳定复现。
比如:
pip freeze > requirements.txt这个命令导出的文件包含了所有包的精确版本。等哪天环境坏了,一条命令pip install -r requirements.txt就能完整恢复。深度学习实验本身就要讲究可复现性,环境管理作为第一步,也应该用工程化的方式来做。
7.3 环境命名规范
我还是个"起名规范强迫症",环境名字起得好,管理起来省心太多。常见起法有两种:
- 按项目名:
exp_segnet、exp_gantest - 按框架版本:
py38_torch2、py39_tf2
个人推荐"项目名+版本"的组合,例如segnet_py38_torch20,虽然稍微长一点,但一眼就能看出来环境和基于什么版本构建,长时间不用的旧环境,光看名字就知道该不该清理。
7.4 最后再分享一个"环境自动加载"的小技巧
有时候我进入一个项目目录后总是忘记激活环境,然后就会把包错误地装进base环境。为了解决这个"手滑",我给自己加了个小机制:在项目根目录放一个.envrc文件(工具的具体方案就不深入了),或者直接在shell配置里加个函数,切换到某个目录时自动执行环境激活。
比如在.bashrc里写一个简版:
venv_cd() { cd "$1" if [ -d "venv" ]; then source venv/bin/activate fi } alias cdv=venv_cd这样输入cdv 项目目录,进入目录的同时就自动激活对应的venv环境,省去了手动激活的步骤。虽然是个很小的技巧,但在频繁切换多个项目的日常里,真的能减少大量重复动作和误操作。
8. 个人经验上的几点补充
说起虚拟环境管理,网上教程一搜一大把,但很多人还是会在实操中翻车。根据我自己的经历,最后补充几点可能容易被忽略的经验。
第一,千万别过度迷信"一个工具打天下"。conda虽然强,但它也有依赖解析慢、环境体积大的缺点;venv虽然轻量,但管不了Python版本。我见过有人只用conda然后环境大得离谱,也有人只用venv,然后为Python版本愁到头秃。最好的方案是"按需混用"——由于深度学习一般要和CUDA打交道,我绝大多数情况用conda创建带指定Python版本和CUDA依赖的环境,项目里的小脚本就用venv随手搞定。
第二,装包顺序有讲究。如果你是做深度学习相关实验,强烈建议先装PyTorch/TensorFlow这类大型框架,再装其他依赖。因为框架的安装经常会影响一些底层基础库(比如numpy等)的版本,如果你先装了一堆numpy、pandas再装框架,框架安装器可能会强制升级或降级这些基础库,造成已有代码不兼容。顺序反过来,先装框架、再装其他,冲突的概率会小很多。
第三,环境目录不要乱移。conda环境和venv环境其实都有"路径绑定"的问题——它们在创建时把绝对路径写进了自己的配置里。如果你建好环境之后,随手把整个conda安装目录或者项目目录搬家了,那么环境很可能就"失联"了,即使路径上看起来还在,激活时也会报错。换机器或迁移目录后,最稳妥的做法是"用配置文件重建环境",而不是直接把环境文件夹拷过去。我从实习到正式做研究,辗转了几台机器之后才深刻体会到这一点。
管理虚拟环境这件事,看起来只是深度学习实验的第一步,做得好却能省下后面无数的时间和精力。我自己为此确实踩过很多坑,写这篇文章把这些关键点都梳理了一遍,希望能让后来者稍微少走点弯路。实验环境的条理性,其实也是科研工程素养的一种体现。