深度学习实验必会:Python虚拟环境创建、查看与删除全攻略
先说一个我见得太多的场景刚入深度学习那阵子今天跑一个图像分类的Demo明天换一个文本生成的模型装包的时候完全不过脑子pip install按了就等。装到第三个项目之前能跑的代码突然开始报错报错信息五花八门折腾一晚上才发现是 numpy 被后装的库悄悄升级了旧代码直接崩溃。这种体验几乎每个拿 Python 做实验的人都经历过。这篇是“深度学习实验基础”系列的开篇聊的是基本功里最容易被忽略、但最值得先学会的一环Python 虚拟环境的创建、查看和删除。别看它简单真正把这一套流程做到随手就来的人后面建模型、查依赖、复现别人的实验会省下大量时间和头发。这篇文章适合刚入门深度学习、还没养成环境管理习惯的朋友也适合项目跑到一半被环境搞崩、想回头系统补一课的同学。1. 为什么深度学习实验必须学会管理虚拟环境1.1 崩溃的真实原因全局环境是个没有分隔的公共宿舍先想一个问题你机器上只有一个 Python所有项目共用一个包目录这个目录通常叫site-packages。不管你是谁的项目、装的什么包最后都堆在同一个房间里。深度学习库对版本又极其敏感A 项目可能要numpy1.24B 项目要numpy1.26公共宿舍里只有一个 numpy而这两个要求同时满足是不可能的。多数新手早期的崩溃都源于此装一个库它顺手把另一个库升级了或者装库的时候某个依赖和你项目里已有的库版本冲突pip 默认不提示直接静默覆盖。等你发现的时候已经分不清是谁动的手。这不是动手能力问题是结构问题——你从一开始就没有给项目之间建立隔离。虚拟环境解决的就是这件事。它给每个项目生成一套独立的 Python 解释器和独立的包目录你在环境 A 里装什么都影响不到环境 B。环境之间互不相识也就不会互相拆台。1.2 深度学习的依赖栈对隔离有更高的要求普通 Python 脚本对依赖冲突的容忍度相对高深度学习则不然。一个典型项目里torch、torchvision、transformers、tokenizers、numpy、pandas、scikit-learn互相之间有大量版本耦合。transformers新版本可能要求特定版本的tokenizers而tokenizers的编译产物还跟 Python 版本绑定。更麻烦的是 PyTorch 本身有 CPU 版和 GPU 版之分对应的 CUDA 工具链不同版本之间差异很大。你复现一个开源项目时作者一般会给requirements.txt里面锁定了每个依赖的版本范围。如果你没有隔离环境直接往全局里装哪怕requirements.txt写得再精确也会被你全局环境里已有的包干扰。有的包版本不会被强制改变但 import 时会加载到错误版本行为就变得不可预测。隔离不是洁癖是深度学习实验的基本卫生。1.3 venv 和 conda 两条路线怎么选目前主流的环境管理工具就两条路线Python 官方自带的venv以及数据科学领域常用的conda。两者底层思路不同适用场景也不同。对比维度venvconda是否自带 Python不必须依赖系统已有 Python自带独立 Python 运行时能否指定 Python 版本不能只能用当前解释器创建可以直接拉取指定版本解释器包管理方式依赖 pip安装 Python 生态包先用 conda 源也可混用 pip隔离级别隔离包目录和解释器路径隔离包目录、解释器甚至系统库学习曲线低一条命令创建稍高但命令也不复杂适合场景轻量脚本、Web 项目、Python 功能练习深度学习、科学计算、多版本 Python 并存我的个人习惯是如果是写点 Python 小功能、跑小 Demovenv完全够用但如果做正经的深度学习实验尤其要配合不同版本的 PyTorch 和 CUDA直接上conda更省心。这篇文章两条路线都会讲到你按自己的场景选一条为主就行。2. 最轻量的做法用 venv 完成创建、激活、查看和删除2.1 创建一个命令拉起独立环境进入你的项目目录比如my_project然后执行python -m venv env_name这个命令的意思是用你当前这个python解释器在env_name这个目录里创建一个独立的虚拟环境。环境名字可以随便起常见的有env、.venv、venv我习惯用env因为短敲命令省事。要特别注意创建时用哪个 Python环境里的 Python 版本就是哪个——比如你系统默认python是 3.9那这个环境就是 3.9。墙上会有个目录生成Linux/macOS 下环境内部是bin/和lib/Windows 下是Scripts/和Lib/。这个差异后面会反复遇到先记着。我强烈建议在项目目录内创建不要专门建一个总目录放所有环境。原因很简单环境跟着项目走删除项目时连同环境整个删掉干干净净不会在系统里留一堆不知道哪个项目在用的环境。delete项目时也不用担心环境残留。2.2 激活为什么终端提示符会变创建完环境后你还需要“激活”它才能让python和pip指向这个环境。激活命令按系统分# Linux / macOS source env_name/bin/activate # Windows CMD env_name\Scripts\activate # Windows PowerShell .\env_name\Scripts\Activate.ps1激活成功后终端提示符前面会出现环境名比如(env_name) yournamecomputer:~$。这个提示符变化很多人不在意其实它是环境是否激活的最直接信号。激活的本质是修改了当前终端的PATH把环境内的可执行文件目录放在最前面。这样一来你在终端里敲python、pip系统会优先去环境目录里找找到的就是环境内的解释器和 pip而不是全局的。你可以验证一下# Linux / macOS which python # Windows where python激活状态下这个命令输出的路径应该指向你项目目录内的环境而不是系统目录。我看到很多同学的排查卡在“我明明激活了装包却装到全局去了”一查要么没激活成功要么是在另一个终端窗口里操作——环境激活只对当前终端有效新开一个终端就得重新激活。2.3 查看确认你不在错误的果篮里查看环境信息最基础的三个命令python --version # 查看当前解释器版本 which python # 查看解释器路径确认是自己那个环境 pip list # 查看当前环境装了哪些包这里有个细节新手容易忽略pip list输出的是当前终端里激活的那个环境的包列表而不是全局的包列表。所以如果你想确认某个包是否装在了某个环境里必须先激活那个环境再看pip list。还可以用一行代码确认当前解释器位置python -c import sys; print(sys.prefix)输出路径里应该包含你的项目目录名。这一步在排查疑难杂症时特别管用比which python更可靠因为有些诡异的运行时环境会干扰 PATH。2.4 退出与删除收拾干净才能走退出环境很简单deactivate运行后终端提示符的(env_name)会消失此时你的终端又回到全局 Python。删除虚拟环境可能是新手最懵的一步venv没有专门的“卸载”命令。删除就是直接删掉那个目录。rm -rf env_name # Linux / macOS # Windows 直接右键删除文件夹即可就这么简单。在删除之前如果这个环境以后可能还要重建建议先导出依赖列表pip freeze requirements.txt这样把环境快照留下来将来想复现这个环境新建环境后执行pip install -r requirements.txt就能按当时的版本状态把包全部装回来。这个习惯我在下文还会反复强调。3. 更符合实验习惯的 conda 方案按 Python 版本和环境列表管理3.1 conda 的核心优势不是“另一个 pip”而是版本级环境如果你只用venv就解决了一个问题隔离包。但还有一个痛点它解决不了——Python 版本本身。深度学习项目之间Python 版本经常各不相同。比如某个老模型只兼容 Python 3.8另一个新项目必须用 3.10。用venv时你得先在系统里装好几个 Python再分别创建环境麻烦。用conda创建环境时直接指定 Python 版本它自己去下载对应的解释器环境自带完整运行时。安装 conda 时我建议选 Miniconda体积小只带基础组件需要什么包再往里装。安装过程不多展开装好之后终端能运行conda --version即可。3.2 创建环境时直接钉死 Python 版本conda create -n torch_lab python3.10这个命令创建了名为torch_lab的环境并指定 Python 3.10。-n是--name的简写后面跟环境名。也可以同时指定通道和安装包比如conda create -n torch_lab python3.10 pytorch torchvision torchaudio -c pytorch但我在实际项目中很少在创建时一口气装很多包因为深度学习生态里pip 依然是安装纯 Python 包最高效的方式。我一般只创建空环境、钉死 Python 版本然后激活环境再用pip install按需安装。3.3 激活、查看、克隆、删除全套命令conda 环境的管理比 venv 稍微多几个命令但都很好记。# 激活 conda activate torch_lab # 查看所有环境 conda env listconda env list的输出里第一列是环境名第二列是环境路径当前激活的环境会带一个星号*。这个列表就是你的“环境档案”环境一多靠这个命令就能迅速看清全局。# 克隆环境 conda create -n new_lab --clone torch_lab克隆非常适合这种场景你费了好大劲调好了一个环境但接下来要做一个实验需要在这个基础上改动很多包又不想伤到原环境。克隆一个出来随便折腾原环境完好无损。# 退出 conda deactivate # 删除 conda env remove -n torch_lab注意conda 删除环境用的是命令不是手动删目录。虽然手动删目录也行但可能会留下注册信息在 conda 的配置文件里重新列出环境时还会有残留路径所以老老实实用conda env remove。3.4 base 环境别乱动Miniconda 自带的默认环境叫base。很多人习惯所有包都往 base 里装图省事。我建议你别这么干。base 环境是 conda 自己的运行基础很多工具脚本默认调用 base 的 Python你在里面装了一堆互相冲突的实验包哪天玩坏了conda 本身都可能跟着出问题。我自己的规范base 环境只保留 conda 自身的组件和极小部分必要工具所有深度学习实验包都装进独立命名的环境里。这样 base 始终干净稳定出问题也能很快定位。4. 贴几个深度学习场景下的真实心得与排查思路4.1 GPU 环境与虚拟环境配合的常见误区深度学习里有个常见误区用了 conda 环境还要不要管 CUDA很多人直接pip install torch然后发现torch.cuda.is_available()返回False查来查去环境没问题是版本装成了 CPU 版。现在的 PyTorch 默认安装通常是 CPU 版GPU 版需要显式指定 CUDA 版本。比如在新建的环境里安装 CUDA 11.8 版pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118装完验证python -c import torch; print(torch.__version__, torch.cuda.is_available())返回2.x.xcu118 True才说明 GPU 版本生效。这个验证步骤在新环境建好、装完核心库之后立刻做一遍能省掉后面无数排查时间。在 conda 里也可以用conda install cudatoolkit但更推荐上面这种直装带 CUDA 的 PyTorch 版本干净省事。4.2 换项目要不要每次新建环境这个问题不少同学问过。我的经验是不要一刀切。日常做探索性小实验几个小脚本共用一个环境完全没问题只要你不乱装会冲突的大库。但遇到以下三种情况我会毫不犹豫新建环境复制别人的开源项目准备复现实验项目之间对 PyTorch、TensorFlow 这类重型框架的版本要求明显不同要跑比较正式的对比实验需要保证每次结果的环境一致性说白了环境是一种隔离成本探索阶段不必过度隔离但一旦进入正式复现和实验记录阶段每个正式项目都应该有独立环境。这也跟版本管理的思想一致——环境隔离做得越好实验的可复现性就越强。4.3 三个高频报错的排查链路我整理了一张高频排查表这些都是新手群里反复出现的问题现象可能原因排查步骤No module named torch没激活环境就开始 pip install / import先conda activate env_name再python -c import torch包安装了但 import 不到pip 和 python 不在同一个环境执行which pip和which python确认路径都在环境目录下版本不符但明明装的是对的全局环境里也有同名包导入时加载了错误版本看路径是否指向环境内用python -c import sys; print(sys.prefix)确认最典型的一种情况你在终端里conda activate了但打开编辑器或 Jupyter Notebook 时它用的还是系统 Python。因为环境激活不向后传递编辑器进程的 PATH 不一定继承你终端的修改。遇到这种问题先确认处理解释器路径别急着卸载重装。这个链路我每次都在群里重复原因就是它太常发生。真正理解了“激活只影响当前终端”这个本质排查起来会快很多。4.4 把环境信息做成“可复现记录”的小习惯最后分享一个我坚持了挺久的习惯对深度学习的实验复现帮助极大每个深度学习项目目录里固定放三样东西——代码、requirements.txt、环境创建说明。代码是你写的requirements.txt是环境里所有依赖的版本快照环境创建说明则记录“这个项目需要哪个 Python 版本、哪个 CUDA 版本、怎么装核心库”。导出 requirements.txtpip freeze requirements.txt如果想连 conda 环境信息一起导出conda env export environment.yml重建环境时conda env create -f environment.yml # 或者 pip install -r requirements.txt这个习惯一开始会觉得多余但等你要复现几个月前的结果、或者把一个项目从一台机器搬到另一台机器时真的能救命。我现在建环境已经是肌肉记忆了开新项目第一件事不是写代码而是先创建环境、装好核心依赖、导出 requirements然后才开始写实验。虚拟环境这关过了后面做实验才是真正的“实验”而不是每天都在跟环境搏斗。下一篇我打算接着写环境移植、pip 和 conda 混用时的注意点以及 Jupyter Notebook 内核和虚拟环境的绑定这些都是实际操作中绕不开的话题。如果你在环境管理上也踩过什么坑欢迎按这篇文章的排查思路先自查一轮大多情况下问题都出在“这个终端真的激活了吗”这一根手指头上。