
刚接手一个老项目代码还是 Python 3.6 的语法跑起来要用 Django 1.11另一边新项目要求 Python 3.9依赖库里用了一堆 3.7 之后才有的新特性。如果只装了一个 Python这两边来回切换就是灾难——装完老项目依赖再切新项目一升级就把环境弄坏了。后来我彻底用 Anaconda 把乱七八糟的 Python 版本管起来才算解脱。这篇文章就是写给被多版本 Python 并存折磨的人看的。核心思路很简单Anaconda 自带一个叫 conda 的环境管理工具它可以在一台机器上创建多个互相隔离的 Python 环境每个环境里面可以装不同版本的 Python、不同版本的包互不影响。下面直接把我实际配置过程中的操作、踩过的坑、以及最后总结出的最佳实践完整列出来有需要的照着抄就行。1. 为什么一个 Python 走天下走不通先说说我遇到的真实情况你大概也碰到过类似的。我做数据分析时经常要跑别人写的开源项目A 项目用的是 TensorFlow 1.x只支持 Python 3.6B 项目是新的 PyTorch 代码建议 Python 3.9 以上C 项目则是自己维护的小工具随便什么版本都行。最开始我图省事给系统 Python 升级到 3.9结果老项目一启动直接报语法错误。后来退回 3.6新项目又跑不起来来回折腾了一天心态直接崩了。1.1 依赖冲突的本质包之间会互相踩Python 项目的依赖关系是一个树状结构你装 A 包时它会自动带上 B 包、C 包而 B 包和 C 包又有各自的版本要求。不同项目对同一个包往往要求不同版本比如项目甲需要numpy1.19项目乙需要numpy1.24这两个版本还不能共存。你不可能靠系统 Python 的 site-packages 同时满足两边的需求。这时候环境隔离就是唯一的正解。每个项目趴在各自的环境里你有 Python 3.6 环境、Python 3.9 环境、Python 3.11 环境每个环境内部再装各自的 numpy、pandas、torch井水不犯河水。1.2 隔离方案对比为什么选 conda做环境隔离的工具不止 conda 一个。Python 自带的venv可以创建虚拟环境pyenv也可以管理多个 Python 版本。我把这三个方案放在一起对比过工具管理 Python 版本管理非 Python 依赖跨平台学习成本venv不能复用系统已装版本不能较好低pyenv virtualenv能不能一般中condaAnaconda 核心能能很好中这里的关键差异是venv本身不解决 Python 版本问题它只是给指定 Python 解释器创建独立的包空间pyenv能装不同版本的 Python但装完以后包的管理还得靠 virtualenv 或者 venv 配合。而 conda 把这两件事合并了——用conda create -n 环境名 python3.9一条命令Python 解释器和后续安装的包全部落在独立目录里。还有一个容易忽略的点conda 不仅能管 Python 包还能管非 Python 的依赖。比如pytorch在 conda 里安装时会自动帮你匹配对应的 CUDA 计算工具包这是 pip 经常做不到的。1.3 conda 能管的不只是 Python 解释器很多人以为 Anaconda 只是Python 包合集其实它是完整的包管理和环境管理工具。用 conda 你可以安装 Python、R、C 编译器运行时等不同语言的运行环境也可以精确安装某个版本的 NumPy、OpenCV 这类带二进制编译产物的包。因为 conda 自己管理依赖不单纯依赖系统上已有的动态链接库所以对底层库的版本控制比 pip 更严格。这也意味着当你在工作中遇到我明明装了某个包但程序启动时还是提示找不到某个底层库这类问题时用 conda 重建干净环境往往是规避问题的最快路径。2. 安装 Anaconda 时那些回头就晚的选择Anaconda 的安装本身不难网上一搜教程一大把但有三个选择我建议你在安装时就确定好不然后面要返工。2.1 下载渠道和安装包选择Anaconda 官方提供两种安装包包含完整 conda 和默认环境的图形安装器大概 500MB 以上以及只有 conda 和最小依赖的 Miniconda约 80MB。如果你不是特别需要 Anaconda 预装的那一两百个科学计算包我更推荐 Miniconda安装快默认环境干净后续要什么包自己装。我最初装的是完整版 Anaconda后来发现默认环境里的很多包根本用不上占空间不说升级还偶尔出兼容问题后面换成了 Miniconda 反而省心。官网如果下载特别慢可以用国内镜像站清华、中科大都有同步。下载时注意区分你的操作系统Windows 用户下载.exe格式macOS 用户看芯片选 Intel 或 Apple Silicon 版本Linux 用户选.sh脚本。2.2 安装时Add Anaconda to PATH到底勾不勾这是 Anaconda 安装过程中最有争议的选项。Windows 安装器里面有个 Add Anaconda to my PATH environment variable默认是不勾选的。我强烈建议不要勾选。勾了虽然能直接在 CMD 或 PowerShell 里输conda命令但 Anaconda 的 Python 会变成系统的默认 Python影响系统里其他依赖 Python 的软件比如某些 CI 工具、Git 的部分插件容易出现明明我卸载了 Anaconda为什么 python 命令还能用这种问题。不勾选的话日常操作通过 Anaconda Prompt 或 Windows Terminal 打开后进入 conda 的 base 环境也很顺手。后面想要在任何终端都能用 conda可以在安装完后执行conda init它会自动修改 shell 配置文件这个比安装时勾 PATH 更可控。2.3 装完先做三件事验证、更新、配置镜像装完后第一步验证安装是否成功。Windows 在开始菜单找到 Anaconda Prompt或者 Miniconda Prompt输入conda --version能输出版本号就说明 conda 本体没问题。再检查 Pythonpython --version这时候显示的版本是默认 base 环境Anaconda 自带的 Python 版本比如 3.11.x。第二步是把 conda 本身更新到最新版Anaconda 自带的 conda 可能不是最新的conda update conda conda update --all第三步配置国内镜像源。这一步很重要如果跳过后面创建环境和装包时下载速度会非常慢。我直接用清华的 Anaconda 镜像腾讯云和阿里云也有对应镜像服务执行如下命令生成或修改~/.condarc文件conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --set show_channel_urls yes配置完可以用conda config --show channels查看当前生效的源列表。注意如果你用的是较新版本的 condamain和free两个 channel 已经足够msys2之类的需要时再单独加。pip 的镜像也一并配好不然你在 conda 环境里用 pip 装包还是会慢pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple下载慢的问题后面我还会在排查章节详细展开这里先保证初始配置不踩坑。3. 核心操作从创建环境到切换环境的完整链路这一部分是 Anaconda 管理多版本 Python 的重头戏。环境创建、激活、切换、销毁每个动作都是有为什么的我尽量把命令和背后的逻辑都讲明白。3.1 用 conda create 创建指定 Python 版本环境创建一个指定 Python 版本的新环境语法是conda create -n 环境名 python版本号比如我要创建一个 Python 3.9 的环境命名成py39conda create -n py39 python3.9conda 会先解析依赖关系然后显示一个安装计划列表。确认后它会去配置好的镜像源里下载对应版本的 Python 解释器和基础依赖包。这里有几个关键点要注意-n后面跟的是环境名环境名不要带空格建议一律小写加数字和下划线。创建环境时可以直接追加要安装的包比如conda create -n py39 python3.9 numpy pandas一次性把事情办完。如果你不需要 conda 默认附带一堆基础库可以用--no-default-packages参数建一个裸环境适合对包洁癖比较强的人。每次创建环境都会在一段时间内占满 CPU 和网络因为它在完整解析和下载。我创建新环境时经常顺手把别的任务停一下避免互相拖慢。3.2 激活、切换、退出环境环境创建好以后使用前必须激活它。不同操作系统激活命令有区别WindowsCMD 或 Anaconda Promptconda activate py39Linux / macOSconda activate py39激活成功后终端提示符前面会多一个(py39)前缀。看到这个括号你才能确定当前正在使用的是py39环境而不是 base 或系统环境。退出当前环境conda deactivate回到 base 环境。切换环境的本质就是激活另一个环境名不需要先 deactivate 再 activate直接conda activate 新环境名就会自动切换。3.3 在环境里安装包以及为什么不要污染 base激活了某个环境之后安装包的命令都是conda install 包名。比如conda install numpy conda install pandas conda install pytest你可能会问为什么不直接conda install到 base 环境里这样所有环境都能用不好吗我的经验是尽量别这么干。base 环境是 Anaconda 自己运行 conda 和很多内置工具的地方你把乱七八糟的包都装进去时间长了依赖关系会越来越乱升级 base 环境时经常因为依赖冲突失败。我个人的理解是base 环境只保留 conda 和极少数全局工具项目相关的包一律装进独立环境。如果某个包在多个环境都要用合理的方式是每个环境各装一份磁盘多占一点但换来了极大的隔离程度这个代价完全值得。3.4 查看环境列表、当前环境、环境存储位置查询本机所有环境conda env list输出大概长这样# conda environments: # base * /home/user/miniconda3 py36 /home/user/miniconda3/envs/py36 py39 /home/user/miniconda3/envs/py39其中带*的是当前激活的环境。从这里也能看到每个环境本质就是miniconda3/envs/下的一个文件夹环境名就是文件夹名。如果你直接进入这个目录操作也能找到该环境下独立的python.exe和Scripts目录这是理解整个环境隔离机制的关键。查看当前环境更精确的方式conda info输出里包含当前环境的 Python 版本、conda 版本、环境根路径、channels 源等详细配置排查问题时会频繁用到。4. 激活环境没反应和装包慢如蜗牛的实战排查新手最容易卡住的两个地方一个是环境激活不生效一个是从国外源下载包慢到怀疑人生。这两个问题我在不同机器上都踩过排查过程写下来遇到类似情况可以直接照做。4.1 排查链路一conda activate 报错没有这个命令用 Windows 用户举例。安装时如果没有勾选 Add to PATH直接在原生 CMD 里输入conda activate py39会遇到conda 不是内部或外部命令也不是可运行的程序或批处理文件。或者在某些 Linux 终端里遇到CommandNotFoundError: Your shell has not been properly configured to use conda activate.这个问题其实很好理解conda 的可执行文件路径不在当前 shell 的 PATH 环境变量里shell 当然找不到它。解决方法是初始化 shell在 Anaconda Prompt或者任何能运行 conda 的终端里执行conda init它会自动检测你当前使用的 shellbash、zsh、powershell、cmd 等然后往对应的配置文件中写入 conda 的初始化脚本。执行完以后重启终端conda activate就能用了。如果你装的时候勾了 PATH原生 CMD 里能输conda但激活环境时报Your shell has not been properly configured to use conda activate那问题定位为 conda 没有在 shell 初始化时注册activate钩子同样是执行conda init解决。4.2 排查链路二环境里用 pip 装包但 import 时报 ModuleNotFoundError这个问题是环境隔离理解不到位时最容易犯的。你在py39环境里执行pip install requests然后跑 Python 脚本import requests结果ModuleNotFoundError: No module named requests但明明 pip show 显示这个包是装上了的。这类问题 90% 的原因是当前的 pip 属于另一个环境。比如你在 py39 环境里激活状态失效了或者你是在 base 环境里用的 pip但执行脚本时用的是 py39 的 python。排查步骤确认当前环境前缀看提示符前面有没有(py39)。执行which python或where python看 Python 解释器的路径是不是在envs/py39/下。执行which pip或where pip看 pip 解释器的路径是不是在envs/py39/下的Scripts/pip.exe。如果在 py39 环境里这两个路径都对但 import 还失败继续往下查执行pip list确认包确实存在。执行python -c import sys; print(sys.path)看当前环境是否真的在路径列表里。最后一步排查的是多环境干扰有些人的PYTHONPATH环境变量指向了另一个环境的 site-packages导致 Python 导入路径混乱。解决方法是取消PYTHONPATH环境变量让 Python 完全走 conda 环境默认的路径。4.3 排查链路三创建环境和安装包时下载极其缓慢你可能会觉得既然是 Anaconda 官方工具直接从官方 CDN 下载不就行了现实是官方源经常慢到几十 KB/s甚至直接卡死。排查第一件事就是确认当前用的 channel 是什么conda config --show channels如果显示的还是一堆repo.anaconda.com的地址说明之前配置的镜像源没生效。这时候把官方源先删除再添加国内镜像源conda config --remove channels https://repo.anaconda.com/pkgs/main/ conda config --remove channels https://repo.anaconda.com/pkgs/free/也可以直接手动编辑~/.condarc文件把里面的 channels 替换成镜像站地址然后保存。配置生效后再次创建环境速度能提升几十倍。我实测下来从几 KB/s 提升到十几 MB/s 是很正常的提升幅度。pip 慢的问题同理走国内 PyPI 镜像配置命令我刚才已经写过一次这里再强调一下配好以后pip install的速度会有质的提升。4.4 conda install 和 pip install 混用有哪些坑在同一个环境里conda 和 pip 是可以共存的但混用有讲究。conda 不知道 pip 装了什么pip 也感知不到 conda 的依赖解析规则所以两种方式装同一个包的不同版本时可能把环境搞出薛定谔的依赖状态。我个人建议能用 conda 装的优先用 conda 装conda 找不到的包再用 pip 补。装完了不要随便再切换安装器去装同一个包。比如numpy用 conda 装了 1.21后面又用pip install numpy1.24环境内可能出现两个版本的 numpy 残留虽然 Python 导入时会覆盖但偶尔会出现奇怪的链接错误。5. 环境生命周期管理克隆、导出、删除、备份环境创建出来是拿来用的用久了自然要管理。这一节讲几个和维护相关的核心操作都很实用。5.1 导出环境配置实现项目一键复现当你把一个环境调好后可以把整个环境的包清单导出来。别人拿到这份清单就能创建出和你一模一样的运行环境。导出为标准的 YAML 文件conda env export environment.yml这个文件记录了环境名、channels 源、以及所有 conda 和 pip 安装的包及其精确版本。别人拿到后执行conda env create -f environment.yml就能完全复现你的环境。还有一个更轻量的方式只导出显式安装的核心包不导出所有传递依赖conda list --explicit spec-file.txt用这个文件重建环境时conda 会逐条解析依赖允许在新平台上有一些自动适应的空间。上面两种方式我怎么选如果是做一个演示项目我会用 spec-file如果是部署到多台机器我会用完整导出保证完全一致。5.2 克隆环境如果你想从一个环境复制出一个新环境比如把 py39 环境里的配置完全复制到 py36 里再改少量东西可以conda create -n py36 --clone py39克隆出来的环境包含原环境的包和配置但两个环境后续互不影响。这个命令在我先在一个环境里测试成功后创建最终环境的场景下非常有用。5.3 删除环境和重命名的正确姿势删除环境用的是conda remove -n 不要的环境名 --all加上--all才表示连环境里的所有包一起删除否则只删除某个包。现实里有个尴尬的问题conda 没有直接的重命名命令。要重命名一个环境只能先克隆后删除两步走conda create -n 新名字 --clone 旧名字 conda remove -n 旧名字 --all5.4 清理缓存释放磁盘空间用 conda 装包多了以后缓存目录会积累一大堆下载的压缩包。查看缓存占用conda clean --all这个命令会先提示你确认是否删除所有缓存。我在一台用得比较久的机器上一次清理出了几个 GB 的空间磁盘吃紧时可以定期清理。6. 让环境真正跑起来与 VSCode / PyCharm / Jupyter 的联动命令行把环境设置好只是第一步平时写代码还是在 IDE 里效率高所以最后讲一下怎么把 conda 环境接到各种开发工具里。这一步没配置好编辑器里跑的 Python 可能还是系统解释器导致环境里明明有包编辑器里报找不到。6.1 VSCode 中指定 conda 里的解释器VSCode 装好 Python 扩展后按CtrlShiftP输入Python: Select Interpreter回车会列出当前所有检测到的解释器包括系统 Python各个 conda 环境下的 python.exe从列表里选中你要用的 conda 环境一般会显示类似Python 3.9.XX (py39: conda)的提示VSCode 就会自动用它作为默认解释器。这时候你在 VSCode 里新建终端它也会自动帮你在对应环境里打开。有一个小细节VSCode 里如果没有在列表里看到 conda 环境检查一下 Python 扩展版本和 conda 环境是否已经激活。如果还是不行可以直接在settings.json里指定解释器的绝对路径比如{ python.defaultInterpreterPath: C:/Users/用户名/miniconda3/envs/py39/python.exe }6.2 PyCharm 中配置 conda 环境PyCharm 配置起来稍微绕一点。打开设置File - Settings - Project - Python Interpreter点击齿轮图标选择Add Interpreter再选Conda Environment。这里有两个选项Existing environment选择已经创建好的环境直接浏览到对应目录下的 python.exe。Create new environment在 PyCharm 里直接用 conda 创建新环境填好环境名和 Python 版本即可。选好以后PyCharm 的终端和运行配置都会使用这个环境。要注意 PyCharm 部分老版本对 conda 环境的检测依赖于conda.exe路径如果提示找不到 conda需要在配置里手动指定 Anaconda/Miniconda 安装路径下的conda.exe。6.3 在 Jupyter Notebook / JupyterLab 中切换内核Anaconda 自带了 Jupyter但默认的 Jupyter 只会显示 base 环境的 Python 内核。想让 Jupyter 能直接切换到你创建的 py39 等环境需要在对应环境中安装ipykernelconda activate py39 conda install ipykernel装好后在 Jupyter 界面里点击右上角的选择内核或者工具栏的 Kernel 菜单就能看到Python [version] (py39: conda)这样的选项。如果你想要更通用一点的做法可以在 base 环境安装nb_conda_kernels它会自动把当前 conda 里所有环境注册为内核不用进每个环境单独装 ipykernelconda activate base conda install nb_conda_kernels6.4 环境管理的几个实战建议最后把我自己的习惯分享一下。第一个是环境命名规范我用的格式是项目简写加用途比如nlp-bert、recommend-lightgbm这样环境多了也不会混淆。第二个是版本锁定。项目稳定后把环境导出一份environment.yml提交到 Git 仓库里下次换机器或者别人接手项目一条命令就能跑起一模一样的环境。这是团队协作时最省钱的做法。第三个是不要图省事把所有包装在一个环境里。我在工作中见过不少把 Java 的 JDK 装在一个 conda 环境里、把 Python 3.6 和 Python 3.9 的包混在一个环境里的情况最后都是依赖冲突告终。环境隔离的本质是让每个项目拥有自己的运行空间这个空间越纯粹越干净出问题的概率就越低。第四个是关于 conda 环境在跨平台迁移的注意事项。conda env export导出的配置文件里包含固定版本的包同平台同架构下复现最精确如果是 Linux 导出的环境文件拿到 Windows 上重建某些底层二进制包可能源上就没有对应版本此时建议用conda list --explicit导出的 spec-file或者只导出顶层依赖清单再手动调整。说了这么多核心还是要自己动手把流程走一遍。我第一次创建环境、切换版本、装包踩坑前前后后花了一整天但第二次、第三次就完全自动化了。现在每接一个 Python 项目第一件事就是conda create -n 项目名 pythonx.x知道自己永远不会把系统 Python 搞坏也不用再羡慕别人电脑上各种项目切换自如。这套流程一旦养成习惯Python 版本管理这件事基本上就再也不会成为你的绊脚石。