
写这个系列文章的时候我反复在讲一句话AI 编程能不能顺畅推进很多时候不取决于模型调参有多厉害而取决于你能不能在一小时内把开发环境跑起来。今天这篇是 AI 编程智能体系列的第 06 篇不聊模型不聊框架只聊一个基础但特别重要的事用 Anaconda 把 Python 多环境管明白。很多初学者最开始学 Python 时就是直接去官网下载一个安装包一路下一步装完然后用 pip 装包。这在前几个脚本项目里没毛病但一旦你开始做 AI 相关的项目会发现灾难来得特别快。今天还在 python 3.8 下跑得正常的代码换了台机器或者升级了依赖突然就 import 报错某个项目需要 tensorflow 的老版本另一个项目又必须要新版本的 numpy两个项目在同一个环境里互相打架最后谁都能跑谁都跑得心慌。我自己刚接触 AI 开发时就被这种版本兼容问题按在地上摩擦过很多轮。后来把 Anaconda 用熟这些坑才一个个填平。这篇文章适合谁看刚进入 AI 开发、机器学习方向的新手以及在本地开发时被 Python 依赖搞得焦头烂额的工程师。读完你至少能解决三件事第一知道为什么 Python 环境会乱成这样第二会用 conda 创建独立的 Python 环境不同项目互不干扰第三学会把环境导出、克隆、迁移换机器也能秒级复现彻底告别那种“在我电脑上是好的”的经典悲剧。1. 版本兼容问题从哪来“不是 Python 不靠谱是你只有一个环境”1.1 同一个 Python不同项目需求天然冲突先讲讲底层逻辑。Python 之所以容易出现版本兼容问题不是因为这门语言本身不靠谱而是因为“所有项目共用一套环境”这个思路在项目多了以后必然爆炸。我拿一个实际场景展开。假设你手上同时维护两个项目一个是某图像处理 Demo用到了 OpenCV 和旧版 TensorFlow另一个是某跨平台系统的服务端里面用的是新版本 Python 语法和一些只兼容 Python 3.11 以上的新库。这两个项目如果都装在同一个 Python 环境里会出现什么情况第一个项目要 tensorflow 2.4第二个项目可能要求 tensorflow 2.10 以上的版本。你升级了一个另一个报错你换回旧版新的服务端起不来。更麻烦的是项目 A 装的某个包依赖了低版本 numpy而项目 B 安装新包时 pip 会自动把 numpy 升级到最新然后项目 A 的代码开始出现各种奇奇怪怪的警告甚至数组计算错误。问题的根源就在这里不同项目对依赖包的版本要求经常会形成互相冲突的关系。而这在 AI 领域尤其严重因为 AI 项目的依赖链特别长——一个深度学习框架会牵动几十个底层库底层库之间还有版本锁定关系。你很难手工维护这种复杂的依赖平衡。1.2 我踩过的一个典型“灾难”复盘说一个我曾经实际遇到的场景不点名什么项目了反正挺典型。当时我在本地用 Python 3.7 搭了一个图像分类的小实验跑得好好的。隔了几个月重新打开系统 Python 已经因为装别的工具被升级到了 3.10再跑原来的代码第一个 import 就开始报错。我当时的反应很经典直接硬刚尝试手动安装缺失的包然后又去更新 numpy、scipy一通操作之后环境彻底乱了。最后只能全部卸载重装浪费了整整一个下午。事后我总结了那次事故的三个直接原因第一把系统 Python 和项目 Python 混用了第二所有依赖包都装在同一套 site-packages 里没有隔离第三升级依赖时只顾解决当前报错没考虑对其他项目的连锁影响。如果你现在也在经历类似的事情不用慌。Anaconda 这类环境管理工具就是专门来解决这个问题的。它的思路和路由器很像——你有电脑、手机、电视一堆设备都要上网总不能全挤在一个网口上插个交换机各走各的网线互不影响。conda 就是 Python 世界的“交换机”。2. conda 的核心机制你为什么需要一个“环境管理器”而不是单纯的“包管理器”2.1 conda 管的不只是包更是整个环境聊 Anaconda 之前先把这个工具背后的核心机制讲透。很多人以为 conda 就是 pip 的替代品其实不完全对。pip 的主要工作是“从 PyPI 下载包并安装到当前环境”它管的是包。而 conda 管的是“环境”——一个环境里除了 Python 包还包括 Python 解释器本身的版本、底层依赖库、以及环境和环境之间的隔离关系。这个区别非常关键。你用 pip 装不同的包是装到同一个目录下很难隔离而 conda 可以创建多个相互独立的环境每个环境有自己的 Python 版本、自己的包集合、自己的配置。切环境就像是换了一台虚拟机器A 环境乱成一团B 环境照样干干净净。举个例子。你创建了一个名为 py310 的环境指定 Python 3.10然后再建一个名为 py38 的环境指定 Python 3.8。这两个环境里的 Python 解释器完全是两份独立的东西py38 环境里装旧版 TensorFlowpy310 环境里装新版 PyTorch两者就算依赖完全对立也能在同一台机器上平稳共存。2.2 conda 与 venv、pip 的差异到底在哪里有同学会问Python 标准库不是也带了一个 venv 吗我用它不就行了能问出这个问题说明你确实想过环境隔离这事但 venv 和 conda 的差别很大尤其是在 AI 开发场景下。venv 创建的虚拟环境本质上还是基于你当前系统已经安装的那个 Python 解释器它只能隔离包不能方便地切换 Python 版本。假设你的项目需要 Python 3.6但你系统里只有 3.11用 venv 就很尴尬你得自己去找旧版 Python 安装。conda 就不存在这个问题它在创建环境时会独立下载对应版本的 Python 解释器完全不依赖系统里现有的 Python。还有一个更实际的区别很多 AI 相关的底层库比如 numpy、scipy甚至一部分深度学习框架的预编译依赖在 conda 的默认源里有编译好的二进制包conda 安装时能自动处理这些包的底层依赖关系。用 pip 装同样一个包有时候会遇到“需要先编译某个 C 扩展”的情况而机器上缺编译器就直接报错。我在实际的 AI 项目里同一个 numpy 版本conda 装可能几十秒搞定pip 装却可能因为要编译而耗时更长甚至失败。两者对比我整理了一个表格方便你直观理解对比维度condaAnaconda/Mincondavenvpip管理对象环境包环境仅基于已有 Python包可切换 Python 版本可以创建时指定不行受限于系统 Python不行依赖冲突隔离完全隔离隔离包不隔离解释器不隔离AI 底层库处理预编译二进制自动解析依赖依赖系统环境有时需要编译跨机器复现用 environment.yml 轻松复现需要组合 requirements.txt 等手段需要手动处理从这张表可以看出来conda 是这三者里覆盖面最全的。你会发现做 AI 项目时conda 几乎成了事实标准不是没有道理的。2.3 为什么 AI 项目特别依赖 conda 这种机制再往深处说一点。AI 项目有一类很典型的依赖被称为“依赖地狱”——深度学习框架、科学计算库、GPU 加速库之间存在大量版本耦合关系。比如某个版本的 PyTorch 可能只支持 CUDA 11.8 和 Python 3.8~3.11你换一个 Python 小版本可能框架就编译不通过了。这种环境下你最好有一个工具第一能够在创建环境时精确指定 Python 版本第二能在安装包含底层二进制依赖的包时自动去求解依赖关系第三能够在项目复制、移交、换机器时完整保留环境状态。conda 在这三点上做得都比较成熟这也是我在这个系列里专门拿出篇幅写它的原因。3. 实操全流程从安装 Anaconda 到创建你的第一个专属环境3.1 安装选择Anaconda 还是 Miniconda很多人一上来就问 Anaconda 和 Miniconda 到底装哪个。说下我自己的选择现在我主力推荐 Miniconda。Anaconda 实际上是一个发行版里面除了 conda 之外还预装了 200 多个常用科学计算包。听起来很方便但其实你真正会用的没那么多反而占了大量磁盘空间而且那些预装包的版本可能跟你项目需要的不一致还得再调整。Miniconda 只是一个精简版——它只包含 conda、Python 和很少的几个基础工具其他包你需要什么装什么。这样环境干净依赖关系也清晰出问题也好定位。下载地址这里就不发链接了直接去官网找对应操作系统的 Miniconda 安装包即可。Windows 用户下载 .exemacOS 用户根据芯片选 arm64 或 x86_64 版本Linux 用户一般用 .sh 脚本安装。如果你确实是新手不想折腾那么安装 Anaconda 也完全可以后面的命令逻辑没有任何区别。3.2 安装时的几个我认为比较重要的细节关于安装过程我提醒几个容易被忽略的细节。第一Windows 安装时如果安装程序问你是否要把 conda 加入 PATH 环境变量建议直接勾选。虽然提示说可能影响其他软件但在现在的使用习惯下加入 PATH 能让你在任意终端直接使用 conda 命令否则每次都要去开始菜单里打开特殊的 Anaconda Prompt体验会差很多。第二macOS 和 Linux 用 .sh 脚本安装时默认安装路径在用户目录下一般是 ~/miniconda3不需要用 sudo也不建议用 sudo。如果安装脚本提示是否要自动初始化 conda选择“yes”这会在你的 shell 配置文件中加上自动激活 base 环境的设置。第三安装完成后建议执行一次 conda update conda把 conda 本身更新到较新版本避免一些旧版本的小问题。我见过不少安装后立刻报超时的朋友一查发现是 conda 版本太老默认源解析出问题。3.3 创建环境的完整命令与参数解释启动终端在命令行里敲 conda --version 确认安装成功接下来就可以创建环境了。创建环境的命令很简单conda create -n fastapi-demo python3.10这条命令的含义是创建一个名为 fastapi-demo 的新环境并指定安装 Python 3.10。我来拆解一下每个部分的含义conda create创建新环境的核心命令。-n fastapi-demo-n 是 --name 的简写后面跟环境名称。环境名建议全小写用连字符或下划线命名方便记忆。python3.10告诉 conda 在这个环境里安装哪个版本的 Python 解释器。这一步特别重要因为你从此不需要在系统层面切换 Python 版本了每个环境都可以指定自己的版本。执行命令后conda 会先进行依赖求解然后列出将要安装的包列表让你确认。输入 y 回车它会自动下载并安装。创建完后你可以用下面的命令激活这个环境conda activate fastapi-demo激活成功后终端提示符前会多出 (fastapi-demo) 这样的前缀。这个括号就是你的“位置感”——只要看到它就说明你当前所有的 python 和 pip 操作都发生在这个独立环境里跟其他环境完全隔离。3.4 激活环境后的基本操作与自查手段进入环境后你再安装包就不应该直接 pip install 了。虽然 pip 能用但你要确保自己用的 pip 是当前环境自己的。最好的习惯是时刻记住自己现在在哪个环境里。我自己经常会做的一个自查动作是在刚建好环境后执行两条命令which python python --version这两条命令分别告诉你当前使用的 Python 解释器路径和版本号。如果环境激活成功路径里应该包含你的环境名比如 ~/miniconda3/envs/fastapi-demo/bin/python而版本号就是你创建时指定的 3.10。查完这个你就可以放心地往这个环境里装包了。比如conda install numpy pandas如果某个包在 conda 源里不存在或者你不确定是否有可以用 pip install 顶上。但有一个比较重要的原则在一个环境里尽量先用 conda 安装包conda 装不到再用 pip而且不要混着装同一类东西。原因后面避坑章节我会细讲。3.5 管理环境列表与删除无用环境随着项目增多你会创建越来越多环境需要时不时的“盘一下库存”。常用命令就三条conda env list conda activate 环境名 conda remove -n 环境名 --all第一条列出所有环境第二条切换环境第三条删除一个环境。删除时加 --all 是为了把环境对应的目录一起清掉不要只删除环境记录而留下文件。我个人的习惯是每个项目一个环境项目结束了但环境暂时不删因为可能后续还要复用只有确认某个环境完全没用了才会执行 remove。毕竟重新建一个环境虽然不慢但把里面的依赖一个个装回来还是会花时间的。4. 环境复制与迁移让另一台机器无缝跑起你的项目4.1 用 environment.yml 导出环境状态本地环境搞定了接下来面临一个新问题我要把项目代码传到另一台机器或者同事比如 A 同学想复现我的结果别人怎么快速建立起一模一样的环境以前很多人的做法是导出 requirements.txtpip freeze requirements.txt然后在另一台机器上 pip install -r requirements.txt。但这个方式有两个痛点第一pip freeze 会把环境里所有包都导出包括那些间接依赖版本号固定得死死的换个平台可能就装不上第二它不会记录你的 Python 版本信息对方如果系统默认 Python 版本不同装完依然可能跑不起来。用 conda 的话我更推荐导出 environment.yml这是 conda 管理环境的“标准配方文件”conda env export environment.yml 打开后你会看到类似下面的内容 channels: - defaults - conda-forge dependencies: - python3.10 - numpy1.26.0 - pip - pip: - fastapi0.104.1这个文件的特点是同时记录了 conda 包和 pip 包还记录了渠道channels信息。别人拿到这个文件一条命令就能重建整个环境。不过 env export 有个不方便的地方它会导出一大堆间接依赖版本都锁死了换一台不同系统或不同 Python 版本的机器时可能装得很费劲。所以我在给项目做分享时更常用的是 --from-history 这个导出方式conda env export --from-history environment.yml这个命令只导出你在环境里“主动安装”的那些包忽略自动依赖的那些。好处是文件更精简可读性高很多而且跨平台复现时遇到问题的概率更小。一个典型的精简版 environment.yml 是conda env create -f environment.yml执行后conda 会自动创建一个同名的环境名字在 environment.yml 里记录把里面涉及的所有依赖一次装好。举一个我实际遇到过的例子。之前做一个跨平台系统项目我在 Windows 上调试好的环境A 同学要在 mac 上继续改。我把精简版 environment.yml 发过去他执行 conda env create -f environment.yml等了大概七八分钟环境就起来了。他再跑项目代码除了文件路径要改一改之外依赖层面的报错完全没有出现。这就是配置文件迁移环境的价值。4.2 直接克隆已有环境还有一种场景是同一台机器上你想在一个现有环境基础上做点变化又不希望动原来的环境。比如我在 py310-env 里已经装好了一堆包现在想搞个 py310-dev 环境希望基础包都一样但可以再安装新的包做实验。这时候不需要重新一个个装直接用克隆conda create -n py310-dev --clone py310-env克隆出来的环境会保留原环境里几乎所有包和配置。我用的场景一般是新项目需要基于旧项目的依赖但两者后续的发展方向不同。克隆一份两边各自演进互不干扰。这里有个注意点克隆环境时如果原来环境的包是通过 pip 装的克隆后那些 pip 包通常也会被复制进去但这个复制不一定始终可靠。特别是一些用编译安装、或带有平台特定二进制文件的包克隆后可能有隐患。遇到这种包我会选择在克隆后的环境里重新 pip install 一次来确认。4.3 关于 requirements.txt 的正确用法不是说 requirements.txt 没用它依然有它的位置。比如你的项目只依赖纯 Python 包不含复杂的二进制依赖那 requirements.txt 反而是更轻量的选择。我的做法是在 environment.yml 里记录 Python 版本和基础依赖同时再把项目直接依赖的包单独整理成 requirements.txt。这样别人既能用 conda 重建完整环境也能在已有环境里通过 pip 快速安装项目专用依赖。两份文件并存互不冲突。5. 多环境管理进阶与避坑这几种问题几乎每个用 conda 的人都会遇到5.1 包应该用 conda 装还是 pip 装何时该用什么这是环境管理里被问得最多的问题也是不少人环境出乱的根源。我的原则是尽可能用 conda 装conda 没有再用 pip。原因前面提过conda 对底层二进制依赖的处理比 pip 更省心而且 conda 安装的包会被 conda 统一管理以后换渠道、升级、卸载都更可控。但有一种情况建议直接用 pip项目主要是面向 PyPI 发布的新包、纯 Python 包或者一些 conda 源里更新不及时的包。比如某个你在 GitHub 上尝鲜的库通常只有 pip 版本。还有一个很重要的原则不要在一个环境里用 conda 装了某个包然后又用 pip 再去装一遍同一个包的不同版本。这样容易把环境搞成“薛定谔的依赖”——conda 的包索引里是一个版本pip 的 site-packages 里是另一个版本程序 import 时实际用的是哪个可能取决于加载顺序。遇到这种问题排查成本非常高。5.2 不要往 base 环境里塞太多东西这是新手最容易踩的坑。base 环境是你安装 Miniconda 或 Anaconda 时自带的默认环境很多人习惯不管三七二十一所有包都往 base 里装。短期看没问题时间一长base 环境里的包越来越多不同项目的依赖在 base 里互相覆盖最后又是一团乱麻。我的习惯是base 环境只做极简使用。它存在的主要意义是运行 conda 命令本身偶尔用一下 Jupyter 之类的全局工具可以装但项目相关的包一律进项目专属环境。有一个小技巧如果你换新环境时老忘记之前装过什么包可以在创建环境时直接带上常用包conda create -n web-dev python3.11 numpy pandas jupyter这样环境建好之后几个高频基础包就在里面了不用每次重新装。5.3 环境突然不能用常见问题排查速查表使用 conda 时间一长总会碰到一些奇怪的问题。这里整理一个我实际遇到过的排查清单照着顺序来大多数问题都能定位。现象大概率原因处理方式conda activate 后提示 CommandNotFoundErrorshell 未初始化执行 conda init 然后重开终端创建环境时下载特别慢默认源速度有限配置国内镜像源见下方章节环境里 import 报 ModuleNotFoundError但包明明装了激活的环境不对检查 which python 和 conda env list同一个包 pip 装完 import 还是报错pip install 到了别的环境确认当前环境下的 pip使用 python -m pip installconda install 出现 Solve 很久依赖冲突换 conda-forge 源或改用 pip 安装单独版本删除环境后磁盘空间没有释放包缓存残留执行 conda clean --allconda 命令找不到PATH 没配置重新运行安装脚本初始化或手动加 PATH我自己遇到最多的是第一种换了新电脑忘记初始化 shellconda 命令在终端里完全不识别。解决办法就是执行 conda init后面按提示重启终端就好了。5.4 关于镜像源配置的实话实说国内访问 conda 默认源确实经常不给力很多同学装个包卡在进度条上大半天。一个常规操作是把 conda 配置为国内镜像源。配置方式是在终端里执行 conda config 命令写入源地址。举例来说conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --set show_channel_urls yes配置之后conda install 的下载速度会有非常明显的提升。但这里要注意一下不同镜像源的更新频率和包完整性有差异如果你遇到某些包在配置的源里找不到把默认的 defaults 源也加上或者直接用 conda-forge 频道大概率能补上。我不太建议为了求快把太多源都加进来。源多了会拖慢依赖求解速度而且不同源的包混在一起反而容易引入版本不一致的问题。选一两个主流源就够用了。5.5 环境不要太多但也别太少环境管理不是追求数量多而是追求清晰。我见过有人为了测试每个小版本建了一堆环境最后自己都忘了哪个环境对应哪个项目。建议按项目来建环境一个项目一个环境或者一个技术方向一个环境。比如我可以有 ai-train 环境统一放深度学习相关web-demo 环境放 web 服务相关。环境名最好能让你一眼看出用途。我的一些命名习惯是项目型命名如 img-classify、技术栈型命名如 py310-torch、实验型命名如 scratch-play。这比用一个类似 env1、env2 的命名要直观得多两个月后回头看还能记得是干嘛用的。6. 更进一步让这套环境管理真正丝滑起来的几个习惯6.1 conda 升级和缓存清理不要忽略包管理工具本身也要更新。conda 每隔一段时间会有新版本修复一些 bug 或者支持的 Python 版本范围有变化建议有空时执行一下conda update conda另外conda 在安装包时会有缓存时间长了缓存文件占用的磁盘空间非常惊人。我之前清过一次直接释放了十几个 GB。可以定期执行conda clean --all这个命令会清理缓存、临时文件和无用的包文件对系统状态没有任何影响可以放心用。6.2 Jupyter 环境与 conda 环境联动的细节很多做 AI 的同学喜欢用 Jupyter Notebook / Jupyter Lab 写代码。这里有个经常踩的坑你在终端激活了某个 conda 环境并启动了 jupyter但新建 Notebook 时用的却可能是另一个环境的 Python 内核导致 import 又报错。解决方法很简单。在要用的 conda 环境里安装 ipykernelconda install ipykernel python -m ipykernel install --user --name 环境名 --display-name 环境名这样 Jupyter 的 kernel 列表里就会出现对应环境的名字。每次新建 Notebook 时你手动选一下这个 kernel 即可。我在刚接触 Jupyter 时就因为没做这一步反复出现“终端里能用、Notebook 里不能用”的诡异情况后来明白原理后就再也没被困扰过。6.3 这个系列后续可以怎么做环境管理搞定后你的本机开发基础就稳了。这个系列接下来我会写怎么用这些环境去跑完整的 AI 项目包括依赖管理、模型训练、前后端部署等更实操的内容。如果你已经跟着文章把 conda 环境跑通那后面的内容你就能无缝衔接了。最后再分享一个实际的体会。我从最早不懂环境管理、把 Python 环境搞得一团糟到现在能在几分钟内为新项目搭好环境、随手导出配置分享给别人最大的变化就是习惯了把“环境”当成项目的一部分来对待。每次建新项目第一件事就是创建 conda 环境每次项目完成顺手导出 environment.yml每次装新包先判断应该用 conda 还是 pip并且绝不混装。这种习惯养成之后版本兼容问题虽然不能完全消失但它真的很难再打断你的开发节奏了。