☰
Python虚拟环境完全指南:venv与conda的选择、原理及实战避坑
2026/10/27 3:51:59 网站建设 项目流程

写Python项目的人,迟早会遇到一类问题:一个项目要 requests 2.x,另一个项目非要 requests 1.x;昨天还能跑的脚本,今天装了个新依赖之后,直接 ImportError。这时候大多数人第一反应是重装Python,但真正该做的是从一开始就用好虚拟环境。这篇文章想把我平时在venv和conda之间的选择逻辑、背后的原理、以及踩过的坑,一次性讲清楚,顺便把和虚拟环境强相关的Python版本选择问题也说透。

我见过太多新人把项目跑不起来的原因归结为“运气不好”,实际上环境乱七八糟才是根源。只要你写过超过两个Python项目,虚拟环境就是你绕不开的必修课。它不是给“高手”准备的锦上添花,而是给每个实际项目的保底措施。

1. 为什么Python项目离不开虚拟环境

1.1 一次“环境灾难”给我的教训

以前我接了个爬虫项目,里面用着requests、beautifulsoup4,还跑得挺顺。后来帮朋友调一个自动化脚本,需要把某个依赖升级到新版本,顺手就用pip全局更新了一下。结果第二天打开爬虫项目,出现了一堆ModuleNotFoundError和诡异的类型报错。查了半天,才发现是全局环境里几个包的版本被顶掉,互相不兼容了。

这种事在Python开发里太常见了。Python默认的包安装位置是site-packages,不管你是用pip装的还是手动放进去的,所有项目都共用这一份包仓库。表面上看很方便,实际上等于所有人都挤在一个仓库里改东西:A项目把requests升到新版,B项目可能就废了;C项目装了个不兼容的numpy,D项目跟着遭殃。这就是典型的“依赖地狱”。

1.2 虚拟环境到底解决了什么问题

虚拟环境做的事情,说白了就是给每个项目开一个独立的小房间,房间里各自有一份site-packages,互相看不见、也摸不着。一个项目升级了什么,删了什么,统统影响不到其他项目。

你可以这么理解:全局Python就像一个公共厨房,锅碗瓢盆都是公用的,谁都可以拿去换,一个人换完别人就没法用了。而虚拟环境是给每个项目单独配了一套厨具,各用各的,谁都不耽误谁。

关键是,虚拟环境改变的只是一些环境变量和路径,你要用的还是同一个Python解释器(在venv场景下),或一份独立的解释器副本(在conda场景下)。它的作用范围只影响当前激活的终端会话,不影响整个系统,所以非常安全。学会用虚拟环境之后,你再也不用为“这个项目怎么跑不起来”这种问题自责了,绝大多数时候问题都不在代码,而在环境。

2. venv:Python自带的轻量方案

2.1 创建和激活venv的基础命令

venv是Python 3.3开始内置的模块,3.5之后官方就明确推荐用venv管理项目环境。它的最大优点是零安装、不依赖额外工具,只要有Python解释器就能用。

进入项目目录,然后执行:

# 创建一个虚拟环境,习惯上我叫它 .venv python -m venv .venv

这条命令会在当前目录生成一个.venv文件夹,里面有一整套独立的Python运行环境。Windows和macOS/Linux的激活方式不一样:

# Windows(CMD或PowerShell) .venv\Scripts\activate # macOS / Linux source .venv/bin/activate

激活之后,终端提示符前面会出现(.venv)字样,这时候你敲python和pip,用的都是这个环境里的,而不是系统全局的。退出就执行一行:

deactivate

删除环境更简单,直接把.venv文件夹删掉即可。干净利落。

这里有个小细节:为什么不直接叫venv?因为venv和Python模块名重叠,容易出歧义;而.venv开头有个点,隐藏属性更好,很多IDE也会自动识别,所以业界普遍用.venv。

2.2 venv的原理:一份独立的环境快照

很多人用完venv只知道“能用”,但没仔细想过它到底做了什么。一个venv环境里有三个关键部分:

  1. Scripts/(Windows)或bin/(Linux/macOS):存放python.exe、pip等可执行文件的快捷方式或复制版本。
  2. Lib/site-packages/:这是独立包仓库,pip安装的包都放在这里。
  3. pyvenv.cfg:记录这个环境指向的“基础Python解释器”路径。

当你在Windows上激活环境时,系统PATH变量里的优先级变了,python命令会被重定向到.venv\Scripts\python.exe,随之而来的pip也是这个环境里的。所以你在环境里装什么包,都只会落到.venv\Lib\site-packages下面,和其他项目完全隔离。

2.3 用requirements.txt管理项目依赖

venv本身只管隔离,不负责记录依赖。真正把依赖管理起来的是requirements.txt。

当环境里的包都调好之后,执行:

pip freeze > requirements.txt

别人拿到项目后,创建环境、安装依赖两步搞定:

python -m venv .venv .venv\Scripts\activate pip install -r requirements.txt

pip freeze输出的是一份带版本号的清单,比如numpy==1.26.2。但要注意,它会把当前环境里所有包都列出来,包括一些间接依赖,这在多人协作时会造成一定的“干扰噪声”。我的习惯是:

在README里写清楚顶层依赖(比如requests、flask),然后用pip freeze生成的完整清单做本地复现依据。两边都不落下。

2.4 venv的边界在哪

venv适合“依赖简单、系统里已经有合适版本Python”的场景,比如写脚本、做小工具、做Web后端。但它有两个比较明显的短板:

  • 不能方便地管理不同的Python版本。venv只是基于当前这个解释器创建环境,如果你想在一个项目上用Python 3.9、另一个项目上用Python 3.11,光靠venv难以切换,你需要自行下载不同解释器,然后用类似python3.9 -m venv .venv这种方式指定。
  • 环境不能“搬家”。.venv里很多脚本记录的是绝对路径,把这个文件夹拷到另一个目录或另一台机器上,经常会直接失灵。

所以,一旦项目开始涉及不同Python版本管理、需要复现一个完整的数据科学环境,或者需要在不同机器之间迁移,venv就有点不太够用了。这时候就该考虑conda。

3. conda:跨语言、自带解释器的环境管理方案

3.1 conda和venv的本质区别

conda不是Python专属的包管理器,它来自Anaconda生态,但它能创建Python虚拟环境,而且比venv多了一层能力:conda不仅能隔离Python包,还能直接安装和管理不同版本的Python解释器。

venv的工作方式是“复用现在的解释器,给它新建一个隔离空间”,conda则更像是“申请一台完整的小机器”,解释器、依赖库、系统库全都在小机器里。你可以在conda环境里用Python 3.8,在另一个环境里用Python 3.12,随时切换,互不干扰。

这带来的实际好处很明显:新项目需要一个Python 3.10环境,你不需要去官网下载安装一个Python 3.10再想办法配置路径,直接用conda新建即可。

3.2 conda创建、激活、移除环境的常用操作

我的习惯是用Miniconda而不是完整的Anaconda。Anaconda里预装了几百个包,很多项目根本用不到,白白占空间;Miniconda只有conda加一个干净的Python核心,需要什么再装什么。安装Miniconda之后,最常用的是这套命令:

# 创建一个名为 py39 的环境,指定Python版本为3.9 conda create -n py39 python=3.9 # 激活 conda activate py39 # 安装包 conda install numpy pandas # 查看所有环境 conda env list # 退出环境 conda deactivate # 删除环境 conda remove -n py39 --all

conda create执行过程中会问你是否安装新包,输入y回车就行。这里有一个关键选项:-n表示环境名称,如果你不想把环境放在默认位置,可以用-p指定路径,这就是后面“迁移到D盘”的关键。

命令里创建环境的同时指定Python版本,是conda和venv最大的区别。venv只能选择“当前正在用的解释器”,conda可以直接拉取一个独立Python 3.9解释器到环境里,这也是数据科学、深度学习项目首选conda的原因。

3.3 conda环境迁移:迁到D盘和换机器

热词里很多人问“conda虚拟环境怎么迁移到d盘”,这里分几种情况说清楚。

情况一:还没创建环境,直接把环境建在D盘,最简单:

# 在D盘创建环境目录,名字叫 py39 conda create --prefix D:\AnacondaEnvs\py39 python=3.9 # 激活时需要带完整路径 conda activate D:\AnacondaEnvs\py39

用--prefix之后,环境目录就直接落在D盘,C盘压力小,重装系统也不会丢。

情况二:环境已经创建在C盘默认位置了,想整体搬到D盘。这时候最稳妥的办法不是复制文件夹,而是导出环境清单,再到D盘重建:

# 在旧环境里执行 conda env export > environment.yml

然后到D盘的目标位置,执行:

conda env create --prefix D:\AnacondaEnvs\py39 -f environment.yml

执行这条命令后,conda会根据environment.yml里的依赖清单,把同样的包和版本重新装到D盘新环境里。等环境装好后,把C盘旧环境删除即可。

为什么我不建议直接复制整个环境文件夹?因为conda环境里很多文件(比如脚本、.exe链接路径)会硬编码原来的位置,你把文件夹从C盘复制到D盘,表面上文件都在,一运行就可能出现路径错误,找起来非常头疼。安全省事的核心原则始终是:环境文件用导入导出,不要用文件复制。

3.4 conda配置镜像源和conda init问题

conda默认的软件源在海外,国内装包经常卡住或速度很慢。配置国内镜像源基本是必备操作:

# 以清华源为例 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

pip源也一样,常年在下载边缘痛苦挣扎的可以一次性配好:

pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

很多新手在安装Miniconda后,打开PowerShell执行conda activate,会报错:

CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'. To initialize your shell, run: conda init powershell

这不是环境坏了,而是因为conda还没有把你的shell初始化。解决办法就是按提示执行:

conda init powershell

如果用的是CMD或bash,就分别执行conda init cmd.exe或conda init bash,然后重新开一个终端窗口。初始化之后,还需要确保conda的Scripts目录在系统PATH环境变量里,否则会提示“无法将conda项识别为cmdlet”之类的问题。

4. Python版本选择的思路和配套工具

4.1 怎么选Python版本:不是越新越好

“Python版本选择”和虚拟环境强相关,因为虚拟环境就是版本选择落地的地方。很多人一上来就装最新版,但真实项目里版本选择往往受制于依赖包生态。

举个场景:老项目里用了PyQt5或者其他编译型扩展库,这些库对新版本Python的支持可能会滞后;另一个场景是你想用3.11新特性和更快的性能,但公司里老服务还跑在3.8上。如果不懂版本管理,这些场景都会让你寸步难行。

我一般用这三个标准判断版本:

  1. 项目依赖包支持的Python范围。去PyPI、官方文档或GitHub页面看“Requires: Python >=3.8”之类的声明,选范围覆盖你的那个版本。
  2. 团队和运维的基线。如果公司统一用3.9,你的个人项目最好也贴着这个版本走,方便后续交接。
  3. 新项目优先选择已发布半年以上的稳定版。比如现在3.12早已普及多年,3.13也已经出了,但深度学习领域有些库仍然优先适配3.10/3.11,这个时候就不能盲目求新。

4.2 conda管版本,pyenv辅助切换

conda是目前最省事的Python版本管理方案,因为它一条命令就把解释器版本装进了独立环境:

# Python 3.8环境 conda create -n py38 python=3.8 # Python 3.11环境 conda create -n py311 python=3.11

两个环境共存互不影响,用conda activate随时换。

如果你是非conda用户,不想装Miniconda,那可以考虑用pyenv管理Python版本,再用venv创建项目环境。pyenv负责装解释器,venv负责隔离包。这个组合也很主流,但配置起来比conda多一些步骤。两者选一就好,我自己在刚接触Python时用pyenv,后来项目越来越杂,场地也经常换,就统一切到conda了。

4.3 给环境起名字的实用规则

环境名看着是个小事,实际上很影响效率。见过太多人所有环境都叫test,最后根本分不清哪个是哪个。我建议格式是项目名_用途_版本,例如:

conda create -n spider_requests_311 python=3.11 conda create -n torch_ml_39 python=3.9

这样环境多起来之后,一眼就能看出是哪个项目、哪个用途、哪个Python版本。以后做迁移、删环境、写文档,都能节省不少折腾时间。

5. 实操场景:从建环境到跑通项目

5.1 深度学习项目:conda + PyTorch + cv2

深度学习项目是conda使用率最高的场景之一,因为PyTorch、TensorFlow这类库对版本组合极其敏感。我的标准流程是:

# 创建独立环境 conda create -n torch_ml_39 python=3.9 conda activate torch_ml_39 # 安装PyTorch,注意根据CUDA版本选择index-url pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装opencv,对应热词里的“python下载cv2” pip install opencv-python

这里有个极易踩的坑:conda环境里默认的pip和Python是配套的,但如果你在环境里用的还是全局pip,装的东西就落到别的环境里去了。激活环境后,先执行一下pip --version确认路径在torch_ml_39下再动手。

cv2在Python里对应的安装包叫opencv-python,不少人直接写pip install cv2结果报错。这是热门搜索词背后典型的“包名和import名不一致”问题。

5.2 轻量项目:venv就够

不是所有项目都要上conda。如果你只是写个数据分析小工具,依赖就是numpy、pandas、matplotlib,而且系统里正好有Python 3.10以上版本,venv就完全够用:

python -m venv .venv .venv\Scripts\activate pip install numpy pandas matplotlib

好处是省内存、不引入conda那套庞大的体系、创建速度快。坏处也明显:如果你想在这个环境里再换一个Python小版本,venv做不到,只能删掉重建。

5.3 VSCode里正确配置conda和venv环境

很多人在VSCode里跑代码,明明命令行已经激活了环境,编辑器里用的却还是全局Python。这是因为VSCode的Python扩展默认选择了解释器,而不是跟随终端的环境变量。

正确做法是:按Ctrl+Shift+P打开命令面板,输入“Python: Select Interpreter”,然后从列表里找到你的conda环境,路径一般在:

C:\Users\你的用户名\miniconda3\envs\torch_ml_39\python.exe

选好之后,VSCode右下角的状态栏会显示当前Python环境。如果项目里想固定解释器,可以在项目根目录的.vscode/settings.json里写:

{ "python.defaultInterpreterPath": "C:\\Users\\你的用户名\\miniconda3\\envs\\torch_ml_39\\python.exe" }

这样一来,不管终端有没有激活,VSCode都会按配置好的解释器去跑代码,不再出现“终端里正常、编辑器里报错”的割裂问题。

5.4 图像标注工具labelme也独立建环境

热词里有人搜“conda 安装labelme”。labelme是图像标注工具,它依赖的Qt版本和深度学习项目里其他库经常打架。我的习惯是给它单独建一个环境:

conda create -n labelme python=3.8 conda activate labelme pip install labelme

用完就切回主环境,不干扰其他项目。

6. 常见问题与排查实录

6.1 conda activate报错 run 'conda init' 怎么办

这个错误在Windows、Linux都见过,原因就是shell还没完成初始化。执行:

conda init powershell

然后重开终端,问题基本就解决了。如果是在CMD里,就执行conda init cmd.exe。执行后conda会往PowerShell配置文件里写一段初始化脚本,这是正常行为,不用觉得奇怪。

6.2 “无法将conda项识别为cmdlet”如何解决

这个和上一个不一样,这是conda压根不在PATH环境变量里。常见于安装时没勾选“Add to PATH”选项。解决办法是手动把这两个路径加到PATH里:

C:\Users\你的用户名\miniconda3 C:\Users\你的用户名\miniconda3\Scripts C:\Users\你的用户名\miniconda3\condabin

添加完后重开终端,再执行conda --version验证。

6.3 环境迁移之后路径报错

如果把conda环境文件夹直接复制到D盘,运行时可能遇到“找不到指定路径”或某些exe文件启动失败。原因就是环境内脚本残留了C盘的绝对路径。处理办法是在D盘conda create --prefix D:\envs\py39 python=3.9 --clone 旧环境名,或者干脆用yml重新创建。这个问题的本质原理是环境元数据记录路径,光复制文件不改配置,环境等于残缺的。

6.4 pip install很慢或者失败

先说慢,主要在下载源上。用前面提到的pip config set global.index-url切换镜像源。如果某个包下载后编译失败,多数情况是这个包对当前Python版本支持不完整。解决思路要么降版本换Python,要么换一个预编译轮子来源,比如pip install opencv-python直接装预编译版,不要手动源码编译。

6.5 venv环境能不能迁移

我遇到过直接把项目的.venv文件夹传到别的电脑,然后项目怎么都起不来。venv设计本来就不考虑搬运,因为它绑定创建时的解释器路径和系统库。迁移venv的正确做法是:新机器上重新python -m venv .venv,然后pip install -r requirements.txt。requirements.txt才是venv环境的可迁移载体,.venv文件夹本身不是。

6.6 验证当前环境到底用对了没

出现怪异报错时,先做一次“环境体检”:

python -c "import sys; print(sys.executable)" pip --version

第一行输出的是当前Python解释器的绝对路径,第二行输出pip对应位置。如果发现路径不在你预期的环境里,那问题就出在“环境用错了”,而不是代码问题。这一步是我排查环境类问题的第一步,也是新人最容易跳过去的一步。

最后再分享一个我自己的小习惯:给环境做迁移或重建时,先在旧环境里执行conda env export > environment.yml,然后看一眼yml文件里的name和prefix,把name改成新机器上想用的名字,把prefix手动指向D盘目标位置。这样重建出来的环境既干净又可控,远比复制文件夹省心。环境管理这个事,前期多花一分钟把命令和习惯理顺,后面能省下无数个“找问题找到了夜里两点”的夜晚。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询