news 2026/10/5 8:06:13

Python虚拟环境完全指南:venv与conda创建、迁移及VS Code避坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python虚拟环境完全指南:venv与conda创建、迁移及VS Code避坑

装包的时候出了个怪事:两个项目同时依赖同一个第三方库,A项目被升级到新版本之后,B项目直接启动失败。这种问题老手们一看就懂——Python环境被“污染”了。这也是为什么我每次带新人,第一课永远不是语法,而是让他们先搞清楚虚拟环境到底是怎么回事。

这篇东西专门讲Python虚拟环境的创建,从官方自带的venv,到数据科学标配的conda,再到历史悠久的virtualenv,全部覆盖。重点放在两条大家问得最多的线上:一是conda虚拟环境创建后默认落在C盘,怎么安全迁移到D盘;二是VS Code里切换环境时那些“明明选对了却还是跑错解释器”的坑。适合所有被Python环境问题折磨过的人,不管你是新手还是已经写了两年代码。

1. 为什么虚拟环境是Python开发绕不开的一关

1.1 项目依赖冲突的真实场景

先讲一个我最早入行时的真实经历。当时我在同一台电脑上维护两个后端项目,项目A还在用Django 2.2,项目B已经切到了Django 4.2。Django 2.x和4.x之间的API差异大得离谱,路由写法、中间件机制、ORM的查询行为全都不一样。今天装完项目B的依赖,明天项目A就报错,因为全局的site-packages里只剩下了4.2版本。那段时间我写代码前必做的一个操作就是先看当前pip list里Django到底是几。

再举一个更普通的例子。爬虫项目经常要升级requests库来绕过新的反爬策略,但这个库一旦升上去,另一个处理数据的项目可能出问题,因为新版requests改了SSL证书的默认校验逻辑。你很难要求一个机器上的所有项目都使用同一个版本的第三方库,这就是虚拟环境存在的根本原因。

1.2 虚拟环境到底做了什么

很多人把虚拟环境想得太玄了,其实它只干了三件事:

  • 给当前环境准备了一个独立的第三方包安装目录(也就是site-packages)
  • 设置一个独立的Python解释器入口(conda环境下是完整解释器,venv下则是指向原有解释器的链接)
  • 提供一个激活脚本,激活时把环境目录下的bin或Scripts目录插到系统的PATH最前面

理解第三点非常关键。激活环境本质上就是修改PATH,让python、pip、ipython这些命令优先找到环境内的可执行文件。你激活一个虚拟环境后运行pip install,装进去的包是放到这个环境的site-packages,而不是全局目录,原因就是命令行的PATH已经被改写了。

1.3 三套工具怎么选

目前最常用的三套方案:

工具Python版本管理依赖管理范围适用场景环境默认位置
venv不支持,用哪个解释器创建就用哪个版本仅Python包轻量项目、普通Web开发、脚本工具通常放在项目目录下
virtualenv不支持,需要指定解释器路径仅Python包老项目、需要兼容Python 2的年代遗留项目通常放在项目目录下
conda支持,创建时直接指定Python版本Python包 + 非Python二进制依赖数据科学、机器学习、需要多Python版本并存的场景默认在anaconda3/envs目录下

我个人的经验是:短短几年内,已经不用纠结virtualenv了,venv已经吸收了它的核心能力。真正需要花心思决策的是venv和conda二选一。前者轻、干净、无额外依赖;后者重,但能解决Python版本并存的问题,还能装一些编译好的底层库。

2. 先上手Official标配:venv创建虚拟环境全流程

2.1 创建和激活的基本命令

venv最大的优势在于它是Python官方自带的,Python 3.3之后的版本直接用,不用额外安装任何东西。创建流程非常简单:

# 在项目根目录下执行 python -m venv .venv

生成一个.venv目录后,激活方式因平台而异。

Windows CMD:

.venv\Scripts\activate.bat

Windows PowerShell:

.venv\Scripts\Activate.ps1

macOS / Linux:

source .venv/bin/activate

激活成功后,命令行前面会出现一个(.venv)前缀,这代表当前shell已经在虚拟环境内了。后面执行的所有pip install、python脚本,都会走这个环境。

提示:Windows PowerShell里第一次运行Activate.ps1,经常被默认执行策略拦住,提示“在此系统上禁止运行脚本”。解决办法是先在PowerShell里执行一次Set-ExecutionPolicy -Scope CurrentUser RemoteSigned,把当前用户的执行策略放开,然后再激活。

2.2 创建venv时容易被忽略的参数

venv有几个参数,平时用不上,但特定场景很救命,这里列一下:

参数作用使用场景
--system-site-packages让虚拟环境继承全局已装包机器上已有大量全局深度学习的包,不想重复下载
--without-pip创建后不安装pip极端精简场景,比如离线环境里想手动控制一切
--clear创建前先清空已有环境目录想重建环境又懒得先手动删目录

我在实际项目里基本只用默认参数,尽量让环境保持干净。如果要用全局的包,我宁可把它显式装进虚拟环境,也不会开--system-site-packages这个开关。原因很简单:一旦开了,环境就“不纯”了,出了bug你很难判断到底是环境的依赖问题还是全局环境的干扰。

2.3 退出与删除

退出环境:

deactivate

Windows下同样有效。删除虚拟环境就更简单了,直接把.venv目录删掉即可。不做任何额外清理,因为环境的所有文件都在这一个目录里,删完干干净净。

建议把.venv目录永远放在项目根目录下,并且写进.gitignore,避免提交到版本仓库里。这样做有一个直接好处:换电脑、加新成员时,克隆项目后重建环境非常直观,不会出现“环境在别的地方”这种摸不着头脑的情况。

3. conda虚拟环境创建与克隆:数据科学场景的标配方案

3.1 生命周期管理命令

如果你装了Anaconda或Miniconda,conda就是最顺手的环境管理工具。下面这组命令我已经用了无数遍:

# 创建环境并指定Python版本 conda create -n myenv python=3.9 # 激活环境 conda activate myenv # 退出环境 conda deactivate # 查看所有环境 conda env list # 删除环境(先退出再删) conda remove -n myenv --all

conda create后面不一定要跟python=xxx。如果你只写conda create -n myenv,它会创建一个默认版本的环境,具体版本取决于conda本身的base环境。我强烈建议创建时总是显式指定Python版本,比如python=3.9、python=3.11,这样环境的目的性更强,也避免之后因为版本问题踩坑。

3.2 克隆环境能省掉一半的复制粘贴

克隆的价值在数据科学场景特别明显。我平时会在一个基础环境里装好numpy、pandas、scikit-learn、matplotlib这一套,然后试验新项目时直接克隆出一个新环境:

conda create -n newenv --clone myenv

克隆的环境会拥有与原环境基本一致的包列表。这里有个底层细节:conda在做克隆时对包文件多采用硬链接方式,所以新环境并不会真的把所有包文件再复制一份,而是物理上共享同一份文件,因此速度非常快,磁盘消耗也没有想象中那么大。

但要注意,克隆不能跨Python大版本。你想把Python 3.8的环境克隆成Python 3.9的环境,这是做不到的,只能先克隆再手动升级。另外克隆后建议执行一次pip list,确认关键包的版本是否与预期一致,因为pip部分有时不会复制得很完美。

3.3 conda环境的默认存放位置

Windows上conda环境默认放在C:\Users\你的用户名\anaconda3\envs目录下面,macOS和Linux则是/home/你的用户名/anaconda3/envs。C盘空间紧张的用户,这个位置就是灾难的根源。

查看当前环境路径,可以执行:

conda env list

输出结果会列出每一个环境对应的绝对路径。如果你发现空间告急,下面这一章的迁移方法就是为你准备的。

4. conda虚拟环境迁移到D盘的完整链路

4.1 修改envs_dirs,让新环境直接建到D盘

先说最简单的一招:改conda的配置文件,让以后创建的新环境默认落在D盘。

Windows用户先找到用户目录下的.condarc文件,没有就手动创建一个。在里面加入:

envs_dirs: - D:/conda_envs

保存后重启终端,再执行conda create -n newenv python=3.9,你会发现创建出来的环境路径已经在D盘了。也可以用命令行追加,效果一样:

conda config --append envs_dirs D:/conda_envs

同时,原来的默认路径也可以保留。conda会按照envs_dirs列表里的顺序决定优先使用哪个目录创建环境。如果不想让新环境再往C盘塞,就把默认路径从列表里删掉。

4.2 已有环境怎么搬到D盘:两种方案对比

旧环境迁移,有两种主流做法,合不合适要看环境大小。

第一种是导出环境文件后再重建。操作如下:

# 在源机器上导出环境 conda env export -n oldenv > environment.yml # 在目标位置创建新环境 conda env create -f environment.yml -n newenv

这种方法最稳妥,因为它不是直接拷贝二进制文件,而是重新解析所有依赖,在新位置重建一个等价的“克隆体”,因此不涉及路径写死的问题。缺点是,如果环境里的包非常多,尤其是通过pip安装的包,导出和重建都比较耗时。

第二种是直接用conda pack打包。安装conda-pack后:

conda install -c conda-forge conda-pack # 打包环境 conda pack -n oldenv -o oldenv.tar.gz # 拷贝到D盘,解压后直接激活 mkdir D:/conda_envs/oldenv tar -xzf oldenv.tar.gz -C D:/conda_envs/oldenv

conda-pack的优势是环境面貌完全不变,几十个G的大型环境也能快速迁移。但它对操作系统和conda版本比较敏感,跨机器、跨平台使用容易出问题。

老实说,如果环境总大小不超过两个G,我每次都选第一种,忍住重新下载的时间,换来的是一份干净的、可复现的环境;如果环境大到几个G、装了一堆大型深度学习库,那conda pack才是唯一可行的路径。

4.3 直接复制环境目录为什么不推荐

有朋友会说:“我不导出不打包,直接把envs目录下整个文件夹复制到D盘行不行?”我试过太多次了,结论是:能跑的时候确实能跑,但问题非常隐蔽。

conda环境内部大量脚本和配置文件里记录的是绝对路径。比如Windows环境下Scripts目录里的激活脚本、各种可执行文件中的路径,它们的指向还是原来C盘的位置。你复制完成后,在conda env list里可能根本看不到这个环境,或者激活时报错;即使激活成功了,有些工具(尤其是Jupyter内核)依然尝试读取旧路径,最终莫名其妙地“找不到包”。

路径变了之后想修复,办法也有,比如在环境内重新执行conda install --force-reinstall来刷新路径信息,但这不是所有人都有耐心做的。所以我给普通用户的建议很简单:不要直接复制目录,走导出重建或者conda pack。

4.4 迁移后必须做的三项验证

迁移完成后,不要急着往里面装新包,先验证环境是否真的健康:

conda env list

确认D盘路径下能看到该环境。然后激活它:

conda activate 新环境名

激活后执行python --version,确认Python版本正确;再执行python -c "import numpy"确认关键依赖还能正常导入。最后执行pip list,看看包列表是否完整。这三步都通过了,再继续开发,否则趁早回滚到迁移前的方案。

5. VS Code里切换虚拟环境:配置细节与常见陷阱

5.1 选择解释器不等于选择环境名

很多新手在VS Code里创建完conda环境后,直接在终端里输入python,发现用的还是全局版本,就以为环境没生效。实际上VS Code有一套自己的解释器识别机制。

打开命令面板(Ctrl+Shift+P),输入“Python: Select Interpreter”,会看到列出的所有conda环境和venv目录。选中你创建的那个环境后,VS Code会在项目根目录生成一个.vscode/settings.json文件,内容大致是:

{ "python.defaultInterpreterPath": "D:/conda_envs/py38/Scripts/python.exe" }

之后打开终端、运行Python脚本、启动调试,都会优先使用这个解释器。这里有一个常见坑:如果你用conda删掉了环境,再重建同名的环境,VS Code选中的解释器路径不会自动更新到新环境,还是指向旧的路径。运行代码时十有八九会报“Python环境不存在”。解决办法是删除defaultInterpreterPath,重新执行一次Select Interpreter。

5.2 终端自动激活环境的那个开关

VS Code有个设置项叫python.terminal.activateEnvironment,默认是开启的。它的作用是:当你打开VS Code内置终端时,如果当前已经选中了一个虚拟环境,终端会自动执行激活操作,直接进入该环境。

你如果发现终端里根本没有自动激活,先检查这个设置有没有被改掉。另外,Windows的PowerShell执行策略也可能让自动激活脚本被拦,所以上面的Set-ExecutionPolicy命令依然是必修课。

5.3 launch.json里隐藏的硬编码路径

再讲一个我实际踩过的坑。当时我在VS Code里已经正确选中了conda环境,终端里python指向也正确,但点击调试按钮后,代码用的还是全局环境。查了半天,最后翻到.vscode/launch.json,发现里面写了这样一行:

{ "python": "C:/Python38/python.exe" }

这个硬编码路径直接覆盖了所有解释器选择。把这一行改成:

{ "python": "${command:python.interpreterPath}" }

问题立刻解决。这条经验值得写进备忘录:VS Code里所有涉及Python路径的配置,尽量用变量引用当前选中的解释器,不要写死绝对路径。

6. 环境常见故障排查清单:为什么激活了pip还是装错地方

6.1 conda环境里python和pip不同步

这个问题非常常见,症状是:你已经激活了conda环境,输入python时确实进入了环境内的解释器,但执行pip install时,包却装回了base环境。

原因通常是环境里的pip没有安装或版本混乱。判断方法如下:

where python

Windows上输入上面的命令会列出所有匹配的python路径,第一行是当前生效的。再执行:

where pip

对比两个结果,如果python在环境目录下,而pip在anaconda3根目录下,说明pip没有同步。解决办法是在环境内重新安装pip并规范使用:

python -m pip install --upgrade pip python -m pip install numpy

此后一律用python -m pip install的方式装包,而不是直接敲pip命令,可以极大降低这类问题的发生概率。

6.2 venv环境里pip版本太老

用python -m venv创建的环境里,pip版本通常停留在创建时的那个版本。几个月后,你再pip install一个新发布的库,可能直接因旧pip不兼容而报错。

解决方式很简单,激活环境后执行:

python -m pip install --upgrade pip

升级完再装其他包。这条建议虽然基础,但很多新手被那些看起来莫名其妙的装包报错折腾半天,最后发现只是pip老了。

6.3 Jupyter Kernel连不上虚拟环境

如果你在Jupyter Notebook里运行代码,发现无法import已经安装的包,几乎可以断定是Kernel问题。Jupyter的Kernel是独立于shell的,终端里激活了环境不代表Notebook会使用同一个解释器。

需要手动把环境注册为一个Kernel:

pip install ipykernel python -m ipykernel install --user --name=myenv --display-name "Python (myenv)"

注册以后,打开Jupyter,在Kernel切换菜单里选择“Python (myenv)”,就能保证Notebook使用的是虚拟环境。这个操作在conda环境和venv环境里都适用。

6.4 环境路径里的中文和空格是个定时炸弹

有些用户把环境建在类似E:/项目/我的环境这种路径下,短时间没事,但后续安装某些库,尤其是需要本地编译的库时,会冒出一堆奇怪的编译错误,怎么排查都找不到原因。换成全英文、无空格的路径后,问题直接消失。

这部分经验同样适用于迁移到D盘的场景。路径本身一定要规整,D:/python_envs/py38这类命名方式是最省心的。

7. 给新手的最终建议:按场景选工具,按习惯定流程

从实用主义出发,我建议按使用场景来选:

  • 如果你主要写脚本、写Web后端、做自动化工具,venv完全够用,轻量且没有额外学习成本
  • 如果你做数据分析、机器学习,或者经常需要在多个Python版本之间切换,直接用conda,并且第一时间把环境目录设置到非系统盘
  • 如果遇到年代久远的项目,还在用Python 2,再考虑virtualenv,否则不用管它

工具选定之后,给自己定一套固定流程,我是这样做的:

  1. 每个项目独立建环境,环境名直接反映项目名
  2. 创建完环境后,马上安装项目需要的依赖
  3. 把依赖清单导出保存,养成习惯
  4. 每次重建环境后,第一步验证python和pip路径是否同步
  5. 环境出了问题,优先考虑导出重建,不要花几小时去修

最后分享一个我坚持了很多年的习惯:新建或迁移完环境后,第一件事就是执行包清单导出,把环境的状态固化下来。pip freeze > requirements.txt或者conda env export > environment.yml都行。别小看这个动作,项目出问题需要回滚环境时,这份文件就是你的救命稻草。虚拟环境工具本身再强大,也替代不了备份的习惯。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 8:05:09

工程师成长五阶段:从基础能力到带人能力的完整路径

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 8:03:57

Spring循环依赖深度解析:三级缓存能解决什么,解决不了什么

前几天有个读者跑来问我:网上都在说Spring三级缓存能解决循环依赖,为什么我把两个Service改成构造器互相注入,项目一启动直接报错Requested bean is currently in creation?我瞄了一眼堆栈,回答其实Spring源码里写得很…

作者头像 李华
网站建设 2026/10/5 8:03:55

context-mode:滚动后不再迷失的编辑器上下文导航方案

在很长一段时间里,我写代码都有一个非常难受的体验:光标在几百行甚至上千行的函数里来回跳跃时,一晃神就忘了自己到底身处哪个类、哪个方法。尤其当同事把一个大业务方法写成八百行,我滚动到中间位置,抬头看向屏幕&…

作者头像 李华
网站建设 2026/10/5 8:01:28

Midas FEA在桥梁加固盖梁水化热分析与温度裂缝控制中的应用

1. 为什么桥梁加固绕不开盖梁水化热干桥梁加固这行十几年,盖梁这类大体积混凝土构件的水化热问题,几乎每个项目都会撞上。尤其是采用增大截面法加固盖梁时,新浇混凝土贴着旧混凝土浇筑,水化热散不出去,里外温差一拉大&…

作者头像 李华
网站建设 2026/10/5 8:00:07

红外多目标检测实战:YOLO适配5000张实采图与三格式标签

简介:本资源是一套面向计算机视觉初学者与YOLO目标检测实践者的红外多目标检测教学数据集,专为解决真实场景下小目标、低对比度目标的检测建模难题而设计。包含5000张高质量红外图像及配套标注,覆盖复杂背景、多尺度、多类别目标,…

作者头像 李华