
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 python3.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 python3.8 # 创建环境的同时直接安装常用包 conda create -n deepenv python3.8 numpy scipy matplotlib jupyter常用参数里-n后面跟的是环境名字你可以理解成给这个虚拟环境起的唯一ID。python3.8用来指定这个环境里的Python版本。这里控制好Python版本等于直接决定了环境的上限——很多框架对Python版本有硬性要求在创建阶段就锁定是最稳妥的。我在深度学习实验里通常会加一个步骤先创建环境再装深度学习框架。比如conda create -n pytorch_env python3.8 conda activate pytorch_env # 然后再根据你的CUDA版本选择合适的安装命令 pip install torch1.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文件夹里面包含binWindows下是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 --formatcolumns这里面的隐藏坑在于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 envsconda env list alias cur_envecho Python: $(which python); echo Pip: $(which pip); python --version alias torchvpython -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 我的环境清理周期与存储策略虚拟环境管理不只是创建和删除的操作问题还是一个存储和规划问题。我在用了很长时间之后总结了一套自己的清理策略实验进行中的环境保留着每天或者每周更新依赖。论文复现完成且确认结果的环境导出配置文件后环境本身先留着等论文成果整理后再定是否删除。不再使用且导出配置备份完的环境直接删除节省空间。另外深度学习环境的体积往往很大PyTorchCUDA动辄几个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 python3.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 python3.8 pandas numpy scipy matplotlib一次装一堆其实很多根本用不上。按需安装才是瘦身的最佳方式。6.5 一个问题速查表把经常碰到的问题整理成一张表方便对照排查现象可能原因处理命令或办法激活环境后import包失败解释器与pip不匹配或环境未真正激活which python、pip --versionconda安装依赖缓慢默认源慢或依赖解析复杂配置国内源、用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 python3.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 cdvvenv_cd这样输入cdv 项目目录进入目录的同时就自动激活对应的venv环境省去了手动激活的步骤。虽然是个很小的技巧但在频繁切换多个项目的日常里真的能减少大量重复动作和误操作。8. 个人经验上的几点补充说起虚拟环境管理网上教程一搜一大把但很多人还是会在实操中翻车。根据我自己的经历最后补充几点可能容易被忽略的经验。第一千万别过度迷信一个工具打天下。conda虽然强但它也有依赖解析慢、环境体积大的缺点venv虽然轻量但管不了Python版本。我见过有人只用conda然后环境大得离谱也有人只用venv然后为Python版本愁到头秃。最好的方案是按需混用——由于深度学习一般要和CUDA打交道我绝大多数情况用conda创建带指定Python版本和CUDA依赖的环境项目里的小脚本就用venv随手搞定。第二装包顺序有讲究。如果你是做深度学习相关实验强烈建议先装PyTorch/TensorFlow这类大型框架再装其他依赖。因为框架的安装经常会影响一些底层基础库比如numpy等的版本如果你先装了一堆numpy、pandas再装框架框架安装器可能会强制升级或降级这些基础库造成已有代码不兼容。顺序反过来先装框架、再装其他冲突的概率会小很多。第三环境目录不要乱移。conda环境和venv环境其实都有路径绑定的问题——它们在创建时把绝对路径写进了自己的配置里。如果你建好环境之后随手把整个conda安装目录或者项目目录搬家了那么环境很可能就失联了即使路径上看起来还在激活时也会报错。换机器或迁移目录后最稳妥的做法是用配置文件重建环境而不是直接把环境文件夹拷过去。我从实习到正式做研究辗转了几台机器之后才深刻体会到这一点。管理虚拟环境这件事看起来只是深度学习实验的第一步做得好却能省下后面无数的时间和精力。我自己为此确实踩过很多坑写这篇文章把这些关键点都梳理了一遍希望能让后来者稍微少走点弯路。实验环境的条理性其实也是科研工程素养的一种体现。