我前阵子带几个做深度学习方向的同学搭实验环境,发现十个有八个都卡在第一步——不是 torch 和 tensorflow 装进同一个环境里互相打架,就是 pip 装了一堆包最后自己都分不清哪个项目在用哪个。说到底,都是没把虚拟环境这层基本功打牢。别人都在跑模型了,他还在为版本冲突折腾两天,这种亏我吃得太多,今天干脆把 Python 虚拟环境的创建、查看、删除整套操作整理成文,给刚进实验室的你和所有被环境问题折磨过的人一个能直接照着抄的答案。
这篇文章就是围绕深度学习实验里最基础也最要命的环境管理来写的。你学会之后不仅能分清 venv、virtualenv、conda 这些工具各自该什么时候用,还能亲手建出一个干净的 PyTorch 或 TensorFlow 环境,随时查看自己机器上到底有哪些环境、每个环境里装了什么东西,遇到不想要的环境也能利索地删掉,不留隐患。不管你是只在本地电脑上做实验,还是准备上服务器干活,这套东西都通用。
1. 深度学习实验为什么要死磕虚拟环境
1.1 环境隔离开的是什么
很多新手不理解为啥不能把所有 Python 包都装到同一个目录里。我用一个特别直白的类比给你讲清楚:你手机里同时装了微信和抖音,微信非要某个旧版系统组件才跑得稳,抖音又要新版才能启动,这时候如果你只有一个系统,要么微信崩要么抖音崩,二选一。Python 的全局环境就是这个只有一个系统的手机,你把 torch 1.13 和 torch 2.0 同时 pip 进去,后装的会直接覆盖前装的,然后你某个项目的代码还在调用旧版本的 API,运行时报错报得你头皮发麻。
虚拟环境就是你给每个项目单独开辟出一块独立空间,每个空间里有自己的一套 Python 解释器、pip、第三方库,互不干扰。深度学习实验的依赖重灾区还不止是 torch 版本,cuda 版本、cuDNN、numpy 版本、甚至 opencv 的版本都可能互相牵制。你在环境 A 里做目标检测用 mmdetection,环境 B 里跑强化学习用 stable-baselines3,两边对 numpy 的版本要求就可能是 1.24 和 1.26 这种不兼容的组合,不用虚拟环境,你只能在每次切换项目时反复卸了装、装了卸。
1.2 选工具的决策逻辑
不少人一上来就问:venv 和 conda 到底该学哪个?我的建议是分情况看,没有绝对的答案。如果你只是管理 Python 层面的包,那 Python 自带的 venv 模块完全够用,零额外依赖、轻量、干净。如果你还要管理 Python 版本本身,比如某个项目必须用 Python 3.8,另一个项目要 Python 3.10,那你用 conda 更省心,它连解释器版本一起管了。
深度学习场景里还有第三种情况,就是依赖里有需要编译的包或者二进制库,比如某些旧版 torchvison 对系统底层库有要求,用 pip 装可能遇到编译报错,而 conda 装的是预编译好的二进制包,更省事。所以我个人在深度学习实验里的习惯是:快速验证小项目用 venv,需要切换 Python 版本或者装带 CUDA 的深度学习框架时用 conda。两者可以共存,并不冲突。
2. 创建虚拟环境:从零到一建起你的深度学习沙盒
2.1 用 Python 内置 venv 创建环境
venv 是 Python 3.3 之后自带的模块,不需要额外安装任何东西。进入你的项目目录,执行下面这一行命令:
python -m venv deep_learning_env这条命令的意思是:用当前这台机器上的 Python 解释器,在当前目录下创建出一个名为 deep_learning_env 的文件夹,这个文件夹就是一个独立的虚拟环境。里面会自动生成 bin 目录(Linux 和 macOS)或者 Scripts 目录(Windows),以及 include、lib 等子目录。你的环境名可以自己取,我习惯用项目相关的名字,比如 face_recognition_env、rl_simulation_env,一眼就能看出是干什么的,千万不要取 test、venv、env 这种烂大街的名字,环境一多你自己都会认错。
创建完成后激活它,在 Linux 或 macOS 上执行:
source deep_learning_env/bin/activateWindows 上执行:
deep_learning_env\Scripts\activate激活之后你会看到命令行提示符前面多了一个环境名,类似(deep_learning_env) yourname@machine:~$,这就表明你现在已经钻进这个独立沙盒里了。在激活的状态下,你所有pip install的包都会装到这个环境的 site-packages 里,而不是你的全局 Python 目录。
2.2 用 conda 创建带指定版本的 Python 环境
如果你需要在深度学习项目里用特定版本的 Python,或者想顺便管理 CUDA 相关依赖,conda 是更优解。创建一个名为 dl310、Python 版本为 3.10 的环境:
conda create -n dl310 python=3.10命令执行后 conda 会检查当前软件源里的 Python 3.10 包,然后列出一堆准备安装的依赖让你确认,输入 y 回车就行。这里我强烈建议你加一个参数:
conda create -n dl310 python=3.10 -y加 -y 的意思是自动确认所有询问,不需要手动输入 y,省一步是一步,命令写熟练了之后你会感谢这个参数的。
创建完成后激活:
conda activate dl310你注意看命令行提示符前面会变成(dl310),这和 venv 一样,只是后台的实现机制不同。conda的虚拟环境通过环境变量和文件目录实现隔离,其实底层更像是把不同版本的解释器、库、包以目录树的形式按环境区分,切换环境时只需要调整环境变量指向即可,因此切换速度很快,包也都在各自环境的目录下,不会污染全局。
2.3 创建环境时的 Python 版本到底怎么定
深度学习项目对 Python 版本的要求不是越新越好,哪怕 Python 3.12 已经出了很久,很多框架的预编译包对 3.12 的支持依然滞后。我在实际踩坑中总结出的安全区间是:PyTorch 官方稳定版对 3.8 到 3.11 支持最好,TensorFlow 2.x 对 3.8 到 3.10 最稳,如果你在做老项目复现,3.7 甚至 3.6 都有可能被用到。所以创建环境前第一件事是去你要用的框架官网上看它声称支持的 Python 版本范围,再决定环境版本,而不是随手一个 3.11 就往上冲。
用 venv 创建环境时,它默认使用你当前系统 PATH 里指向的那个 Python 解释器的版本。如果你安装过多个 Python,可以用python3.10 -m venv envname这种方式指定用 3.10 来创建。用 conda 就简单很多,直接在 create 命令里用python=3.10参数指定,conda 会自动找对应的解释器版本。
3. 查看虚拟环境:随时摸清你的实验家底
3.1 查看当前处于哪个环境
有时候你开着好几个终端窗口,每个窗口激活了不同的环境,时间一长自己都忘了当前在哪个环境里干活。Linux 或 macOS 下直接用:
which python它会输出当前 Python 解释器的完整路径,如果路径里包含你环境目录的名字,说明你就在这个环境里。Windows 上可以用:
where python效果类似。还有一个更直接的办法,看命令行提示符前缀,前面带了环境名就一定在环境里,但是前提是激活时终端没被其他配置覆盖掉提示符。
3.2 查看所有虚拟环境列表
venv 创建的环境没有像 conda 那样的集中注册表,它就是一个普通目录,所以“查看所有环境”这件事全看你把环境目录建在哪。如果你按我的习惯把所有环境集中放在某个固定目录下,比如~/venvs/,查看时一个ls就解决了:
ls -la ~/venvs/conda 则提供了官方命令:
conda env list这条命令会列出所有环境,当前被激活的那个前面会带一个星号。执行结果大概长这样:
# conda environments: # base * /home/yourname/miniconda3 dl310 /home/yourname/miniconda3/envs/dl310 tf210 /home/yourname/miniconda3/envs/tf210看那个带星号的就是当前环境。注意 conda 不管你在哪个目录下执行conda env list,它都能列出全部环境,因为它维护了一个环境索引,这是 venv 做不到的。
3.3 查看环境里装了哪些包
这个需求在排查依赖冲突时尤其频繁。venv 环境下激活环境后执行:
pip list它会展示当前环境里所有已安装的包和版本号。如果你只想快速确认某个关键包是否装了、版本是多少:
pip show torchconda 环境下用conda list也可以看到所有包,并且它会额外标注每个包是由 conda 还是 pip 安装的,这个细节在排查问题时会很有用:
conda list我还习惯把环境里的包导出成文件,方便别人复现环境,这个放到后面常见问题部分一起讲。
4. 删除虚拟环境:环境清理时的正确姿势
4.1 删除 venv 创建的环境
venv 环境删除方式极其简单粗暴——直接删目录。但有一个大前提,你必须先退出这个环境。还停留在激活状态时,你在这个环境目录下删文件会碰到权限问题,Linux 下会提示Text file busy,Windows 下会提示文件被占用。正确步骤:
deactivate rm -rf deep_learning_envdeactivate是退出当前虚拟环境的内置命令,退出后命令行提示符前面的环境名前缀会消失,这时候再删就清净了。
如果你用 Windows 且习惯鼠标操作,直接在文件管理器里找到对应文件夹按删除键也行,但前提同样是确保该环境没有被任何终端窗口激活。我建议养成先deactivate再删除的肌肉记忆,因为在 Linux 服务器上你永远是用命令行操作,别指望图形界面。
4.2 删除 conda 创建的环境
conda 提供了官方删除命令,这是最不容易出错的方式:
conda remove -n dl310 --all-n指定环境名,--all表示把环境里所有东西连同环境本身一起删除。命令执行后 conda 会把将要删除的包列表列出来,让你确认,同样可以加-y跳过确认。删除完建议执行conda env list确认一下环境已经从列表里消失了。
如果你不小心在环境激活状态下执行删除命令,conda 会自动拒绝或者提示你,所以一个更稳妥的流程是:
conda deactivate conda remove -n dl310 --all4.3 删除后为什么还要留意缓存
这是个特别容易被忽视的坑。你删了环境只是把实际的包和数据目录清了,但缓存不一定会跟着清除。conda 会缓存下载过的安装包,位置一般在~/miniconda3/pkgs或~/anaconda3/pkgs目录下,删了环境之后这些缓存包还是躺在磁盘上,时间一长可能多出来 5 到 10 个 GB。清理命令:
conda clean -a执行它会把所有缓存、临时文件、未使用的包索引全部清掉。venv 环境没有这种集中缓存机制,因为它的包本身就是从 pip 的全局缓存里下载的,真正影响磁盘的是 pip 的缓存,定时清一下也有必要:
pip cache purge这一步不是必须做的,但我在实践中确实遇到过服务器磁盘被缓存占爆然后训练中途写不了 checkpoint 的惨案,所以环境清理时顺手清一把,没坏处。
5. 用 requirements.txt 和 environment.yml 固化环境
5.1 导出当前环境的关键依赖
你在自己电脑上好不容易把环境配好跑通了模型,过几天上服务器却怎么都复现不出同样的结果,这种经历我相信研究过深度学习的人都不陌生。人为复现环境的靠谱做法是把依赖清单保存成文件,别人拿到这个文件就能一键装出几乎一致的环境。
venv 环境下导出已安装包清单:
pip freeze > requirements.txt生成的 requirements.txt 里每一行就是一个包含版本号的包名,比如:
numpy==1.24.3 opencv-python==4.8.1.78 torch==2.0.1注意pip freeze会把环境中所有通过 pip 安装的包全部列出来,包括依赖的依赖,虽然有时候不够优雅,但对于复现环境来说,越全越好。
conda 环境则有两种导出方式。一种是只导出 conda 显式安装的包,因为很多依赖包是 conda 自动带出来的,不需要一条条记录:
conda env export --from-history > environment.yml另一种是导出完整环境的精确快照,带上所有依赖的精确版本号,适合需要严格复现的场景:
conda env export > environment.yml5.2 从文件恢复环境
有 requirements.txt 后,创建新环境并一键安装依赖:
python -m venv new_env source new_env/bin/activate pip install -r requirements.txt有 environment.yml 后,直接用 conda 从文件创建新环境:
conda env create -f environment.yml它会自动创建 environment.yml 里定义的环境名并安装所有依赖。这个方法我经常用来在不同机器之间迁移环境,基本能做到一次成功。
6. 实操过程与核心环节实现
6.1 完整演示:为 PyTorch 实验创建环境
为了让你看得更清楚,我完整模拟一遍我在深度学习实验中最常干的操作。假设我要在一个新服务器上跑一个图像分类实验,预期用的是 PyTorch 和 CUDA 11.8,系统是 Ubuntu。
第一步检查系统里已有的 Python 版本:
python3 --version假设输出是 3.10,我决定就用这个版本直接建 venv 环境。如果你不确定系统 Python 是哪个版本,也可以先装一个 conda 再统一管理。这里我演示 venv 流。
第二步创建环境并激活:
mkdir ~/dl_projects && cd ~/dl_projects python3 -m venv classification_env source classification_env/bin/activate第三步升级 pip,这一步经常被跳过但我每次都提醒要做,因为预装的 pip 版本很可能偏旧,后续安装包容易出奇怪问题:
pip install --upgrade pip第四步安装核心依赖:
pip install torch==2.0.1 torchvision==0.15.1 torchaudio==2.0.1 --index-url https://download.pytorch.org/whl/cu118第五步安装周边常用库:
pip install numpy matplotlib opencv-python pillow tqdm tensorboard第六步验证环境是否可用:
python -c "import torch; print(torch.__version__, torch.cuda.is_available())"如果输出2.0.1 True,说明环境装好了且 CUDA 可用。到这里,整个环境搭建就算完成了。
6.2 完整演示:用 conda 管理多版本环境
另一种更精细的场景:我手头有三个项目,一个需要 Python 3.8 + TensorFlow 2.4,一个需要 Python 3.10 + PyTorch 2.0,还有一个需要 Python 3.7 + 老版本 mmcv。这种情况下用 conda 分开建环境最合理。
conda create -n tf24 python=3.8 -y conda activate tf24 pip install tensorflow==2.4.1 conda create -n pt20 python=3.10 -y conda activate pt20 pip install torch==2.0.1 torchvision==0.15.1 conda create -n mmcv01 python=3.7 -y conda activate mmcv01 pip install mmcv-full==1.4.0每建一个新环境都是独立的,互不干扰。你的终端可以在这些环境之间随意切换,甚至能同时开三个终端,每个终端各自处于不同的环境,这也是虚拟环境最爽的使用姿势。
6.3 项目目录里到底要不要放环境
这是个争论挺多的话题。我的建议是:本地个人项目,把环境建在项目内部没问题,比如my_project/venv,优点是项目整个目录拷走环境也一起走(不过要注意跨平台拷贝环境有时会失效,因为里的路径和链接是写死的)。但服务器上的共享项目或者多人协作项目,环境必须建在项目目录之外,因为你不能把所有协作人的环境都塞进同一个项目目录里,而且.gitignore里肯定会把环境目录忽略掉,不会提交进仓库。
我更习惯的做法是:建立一个~/venvs/目录统一存放所有 venv 环境,项目目录里只放代码和 requirements.txt、environment.yml。这样既避免了环境目录被版本管理误传,又方便一次性查看所有环境。
7. 常见问题与排查技巧实录
7.1 激活环境后 pip 装的包还是进了全局
这个现象真实出现频率极高。你激活了虚拟环境,然后pip install某个包,最后发现这个包出现在全局 Python 的 site-packages 里而不是环境里。排查顺序:
先执行which pip看看 pip 到底指向哪里。如果输出路径里没有环境名,说明环境没激活成功,或者你激活之后又被某个 shell 配置文件的自动激活脚本覆盖了。另一个常见原因是直接用了pip3命令,某些系统下pip3和pip指向不同的解释器,激活环境后用python -m pip install最保险,因为它是通过当前 Python 解释器去调用配套的 pip 模块,绝对不会指错。
我见过有人在激活环境下执行sudo pip install,sudo 之后命令跑在 root 用户的环境里,直接装到 root 的全局 Python 去了。记住一条铁律:虚拟环境激活状态下,所有 pip 命令都不要加 sudo。
7.2 环境里的包能 import 但命令行运行时报错
比如你激活了环境,里面装好了 jupyter,此时你在终端执行jupyter notebook却提示command not found。原因通常是环境里的 bin 目录没有出现在你的 PATH 里。排查方式:
echo $PATH看输出里有没有环境目录下的 bin 路径。正常情况下激活环境时就会把它加到 PATH 最前面,如果没加进去,极大可能是你用了错误的激活方式,比如在写脚本时忘了先source而是直接bash activate。确保你用对命令即可。还需要留意,如果你通过某个 IDE 或者系统的自动环境管理工具,它们可能在后台改了 PATH,这时候直接新开一个干净的终端窗口再试一次往往就能解决。
7.3 conda 环境下 pip 和 conda 混装导致冲突
这是一种比较常见但是隐患较大的情况。你在 conda 环境里先conda install numpy装了一个版本,后来又pip install numpy升级成另一个版本,两者可能版本不一致,导致某些需要编译扩展的包出现 ABI(应用二进制接口)不兼容的报错。我的稳妥建议是:一旦确立了用 conda 管理这个环境,那么核心依赖尽量用 conda 装,pip 只装 conda 源里没有的包。如果不可避免要混装,至少保证同一时刻同一个包只通过一种方式管理,不要来回切换。
另外一个小经验:在 conda 环境里用 pip 安装包之前,最好先升级 pip 到较新版本,conda 自带的 pip 可能版本很旧,装某些现代包会有 metadata(元数据)相关的兼容问题。
7.4 删除环境时提示目录不存在
这种情况通常是环境名写错了。conda 删除时环境名大小写必须完全匹配,而且如果环境被软链接到别的位置,conda env list看到的路径和实际路径可能不同。先别急着删,执行conda env list拿到准确的环境名和路径,再用完整路径验证一下该目录是否真实存在。确认之后再用conda remove或直接手动删除对应目录。
7.5 虚拟环境磁盘占用过高
训练深度学习模型的环境往往会装大量包,环境目录动辄 5 到 10 GB。如果你一个项目建了三个实验环境,磁盘很快就会被占满。排查哪些环境占得多:
du -sh ~/venvs/*或用 conda 的方式:
du -sh ~/miniconda3/envs/*找出最大的环境后,确认没用了就删掉。另外,如果你习惯在多个环境里都装 torch,每个环境都会单独存一套 torch 的库文件,这些文件可能占好几个 GB。对于这种场景,conda 有一些底层共享机制可以减少开销,但 venv 没有。
8. 一些我在实际项目中沉淀的环境管理习惯
8.1 项目一创建就先固化环境文件
我现在的习惯是任何项目第一步不是先写代码,而是把虚拟环境建好,跑通一个最小验证程序,然后立刻导出requirements.txt或environment.yml存到仓库里。这看起来多了一步,但是好处极大。后面你再往里加依赖,每次加完顺手更新一下这个文件。等换电脑、换服务器或者有队友加入时,直接一条命令全部恢复环境,不需要靠“记忆”来复现,因为你的记忆往往是不完整的。
8.2 环境命名里带版本信息和用途
我见过有人建环境时直接用env1、env2这种命名,等到第三周自己都想不起来env2里到底是什么。我在团队里推的命名规范是项目名_python版本_用途,例如:
face_align_py38 ocr_py39_train detectron2_py310这样conda env list一出来,每个环境是干什么的一目了然,不需要再猜测。venv 环境的目录名同理。
8.3 服务器上禁止随意创建全局环境
实验室的多人服务器上,经常出现 A 同学说“我好像装坏了什么”,然后大家发现全局 Python 的某些包被覆盖了。我的底线是:所有人的实验环境必须建在各自家目录下的独立虚拟环境里,不允许往系统全局 Python 里装任何深度学习相关的包,也不允许对系统 Python 直接做 pip install。这样 A 同学的环境炸了,只要删掉重建,不会影响其他人。
8.4 保持环境最小化
我在创建环境时尽量只装项目依赖的包,不顺手装一堆可能“以后会用到”的包。装得越多,环境间产生隐式依赖的概率越大,排查问题的复杂度也会指数上升。曾经遇到一个环境因为多装了一个旧版 scikit-learn,导致另一个包在运行时莫名报错,定位花了大半天。环境保持干净,问题出现时能快速定位。
9. 创建、查看、删除虚拟环境的速查对照表
我把三种常见工具链的核心命令整理成一张表,方便你查漏补缺,贴在手边即可:
| 操作 | Python venv | conda |
|---|---|---|
| 创建环境 | python -m venv myenv | conda create -n myenv python=3.10 -y |
| 激活环境 | source myenv/bin/activate(Linux/macOS)/myenv\Scripts\activate(Windows) | conda activate myenv |
| 退出环境 | deactivate | conda deactivate |
| 查看当前环境 | which python | conda env list |
| 查看环境里的包 | pip list | conda list |
| 删除环境 | rm -rf myenv | conda remove -n myenv --all |
| 导出依赖清单 | pip freeze > requirements.txt | conda env export > environment.yml |
| 从文件恢复环境 | pip install -r requirements.txt | conda env create -f environment.yml |
表格里每一行命令我都亲自在 Linux 服务器、macOS 笔记本、Windows 工作站上跑过,标注了系统差异的地方就一定有差异。另有一个值得关注的细节:conda activate有时会提示你conda init报错,这是在说你当前 shell 还没有配置好 conda 的初始化脚本,跑一下conda init bash然后重开终端窗口就好。
10. 结尾的一些碎碎念
在我带过的人里,凡是环境管理做得好的,后面项目推进都顺很多;凡是环境一塌糊涂的,三天两头在群里问“为什么我 import torch 报错”“为什么换个机器就全废了”。这些问题的根源往往不是深度学习模型本身,而是最基础的环境隔离没做好。虚拟环境这一套东西,理论上一小时就能学会,但你省下来的是之后无数个小时的排查时间,这笔账怎么算都划算。我自己从刚开始用 venv 记不住命令、到处翻文档,到现在闭着眼都能把 conda 环境配好,中间踩的坑基本都写在这篇里了,希望你能少走这些弯路。