查看: 133|回复: 3

Python虚拟环境venv与conda对比:命令配置与踩坑排查

[复制链接]
发表于 半小时前 | 显示全部楼层 |阅读模式
项目A依赖Django 3.2,项目B要用Django 5.0,如果两个项目共用一个Python解释器,site-packages里的包版本必然打架;更糟的是随手升级系统Python的某个包,可能把系统工具一起弄崩。虚拟环境解决的就是这件事:为每个项目准备独立的解释器副本和独立的site-packages目录,让依赖互不干扰。Python生态里最常见的两套方案是标准库自带的venv和跨语言的conda,下面从命令、配置、脚本自动化和故障排查几个角度做代码层面的对照。

一、先看方案定位

venv是Python 3.3+内置工具,无需额外安装,只管Python包,不管非Python依赖;conda是Anaconda/Miniconda附带的包管理器与环境管理器,除了Python包,还能管理R、C/C++库等系统级依赖,并且能直接安装Python版本本身,代价是体积大、依赖解析慢。同类的还有virtualenv、pipenv、poetry、uv,选择时主要看是否需要非Python依赖、是否需要管理解释器版本、团队统一用什么。

二、venv:创建、激活与目录结构

创建虚拟环境时可以用不同的解释器路径来固定版本,也可以调整pip和site-packages行为:
  1. python -m venv .venv
  2. python -m venv my-project-env
  3. python3.11 -m venv .venv-py311
  4. python3.12 -m venv .venv-py312
  5. python -m venv --without-pip .venv
  6. python -m venv --system-site-packages .venv
  7. python -m venv --upgrade .venv
  8. python -m venv --upgrade-deps .venv
  9. python -m venv --symlinks .venv
  10. python -m venv --copies .venv
复制代码

其中--without-pip用于不预装pip,--system-site-packages允许继承系统已安装包,--upgrade-deps会在创建时顺带升级pip等核心依赖,--symlinks与--copies控制是符号链接还是复制文件(Windows默认复制)。

激活脚本按平台区分,Windows的PowerShell脚本可能被执行策略拦截,需要单独处理:
  1. .venv\Scripts\activate
  2. .venv\Scripts\Activate.ps1
  3. Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
  4. source .venv/bin/activate
  5. . .venv/bin/activate
  6. deactivate
复制代码

激活成功后提示符会出现环境名,例如(.venv) user@host:~/project$。环境目录本身是自包含的,结构大致如下:
  1. .venv/
  2. ├── pyvenv.cfg
  3. ├── bin/
  4. │   ├── python
  5. │   ├── python3
  6. │   ├── pip
  7. │   ├── activate
  8. │   └── activate.fish
  9. ├── Scripts/
  10. │   ├── python.exe
  11. │   ├── pip.exe
  12. │   ├── activate.bat
  13. │   └── Activate.ps1
  14. ├── include/
  15. └── lib/
  16.     └── python3.12/
  17.         └── site-packages/
复制代码

pyvenv.cfg记录了环境与基础解释器的关系,排查解释器来源时很有用:
  1. home = /usr/bin
  2. include-system-site-packages = false
  3. version = 3.12.1
  4. executable = /usr/bin/python3.12
  5. command = /usr/bin/python3.12 -m venv /path/to/.venv
复制代码

安装包前先确认pip指向,避免装到全局环境:
  1. source .venv/bin/activate
  2. which pip
  3. where pip
  4. pip install requests
  5. pip install numpy pandas
  6. pip show requests
  7. pip freeze > requirements.txt
  8. python -m venv new-env
  9. source new-env/bin/activate
  10. pip install -r requirements.txt
  11. deactivate
  12. rm -rf .venv
  13. rmdir /s .venv
复制代码

pip show的Location应落在.venv/lib/python3.12/site-packages下;删除环境也简单,退出后直接删目录即可。项目内建议把环境目录、缓存与字节码写进.gitignore:
  1. .venv/
  2. venv/
  3. env/
  4. __pycache__/
  5. *.pyc
  6. *.pyo
  7. .pytest_cache/
复制代码

三、conda:环境管理与environment.yml

conda的价值在于环境与包都能声明式管理,Miniconda体积小,适合从零搭:
  1. wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
  2. bash Miniconda3-latest-Linux-x86_64.sh
  3. conda install mamba -n base -c conda-forge
复制代码

常用配置包括添加conda-forge渠道、开启严格渠道优先级、切换国内镜像以及关闭base自动激活:
  1. conda config --show
  2. conda config --add channels conda-forge
  3. conda config --set channel_priority strict
  4. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
  5. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
  6. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
  7. conda config --set show_channel_urls yes
  8. conda config --show-sources
复制代码

~/.condarc示例,auto_activate_base设为false可以避免每次开终端都进base:
  1. channels:
  2.   - conda-forge
  3.   - defaults
  4. channel_priority: strict
  5. auto_activate_base: false
  6. show_channel_urls: true
复制代码

环境层面的创建、克隆、导出与删除:
  1. conda create -n myenv python=3.12
  2. conda create -n myenv python=3.12 numpy pandas matplotlib
  3. conda env create -f environment.yml
  4. conda activate myenv
  5. conda deactivate
  6. conda env list
  7. conda info --envs
  8. conda create -n myenv-clone --clone myenv
  9. conda env remove -n myenv
  10. conda remove -n myenv --all
  11. conda env export > environment.yml
  12. conda env export --no-builds > environment.yml
  13. conda env export --from-history > environment.yml
  14. conda list
  15. conda list -n myenv
复制代码

包管理命令与pip的对应关系:
  1. conda install numpy
  2. conda install numpy=1.24.0
  3. conda install -c conda-forge numpy
  4. conda install numpy pandas scipy
  5. conda update numpy
  6. conda update --all
  7. conda remove numpy
  8. conda search numpy
  9. conda search "numpy>=1.24"
  10. conda install package_name || pip install package_name
复制代码

environment.yml可以同时写conda依赖和pip子依赖,还能声明环境变量:
  1. name: my-project
  2. channels:
  3.   - conda-forge
  4.   - defaults
  5. dependencies:
  6.   - python=3.12
  7.   - numpy>=1.24
  8.   - pandas>=2.0
  9.   - scikit-learn
  10.   - matplotlib
  11.   - jupyter
  12.   - pip
  13.   - pip:
  14.     - requests>=2.28
  15.     - black>=24.0
  16.     - ruff>=0.1
  17.     - pytest>=8.0
  18. variables:
  19.   MY_ENV_VAR: value
复制代码

需要注意conda与pip混用的风险:pip安装的包conda并不知情,后续conda更新依赖时可能覆盖或破坏pip装进来的包。稳妥做法是优先conda,找不到再用pip,并且不要把pip当成conda环境里的默认手段。

四、venv与conda的取舍

功能上:venv不支持管理Python版本,需要系统已装对应解释器,只管Python包,不支持非Python依赖,环境导出靠pip freeze;conda支持任意Python版本、支持C库和R包等系统级依赖,环境可克隆、可导出,但依赖解析用SAT求解器,明显更慢。

性能上:创建venv约1到2秒,conda通常10到30秒;venv环境本体约20到30MB,conda环境约200到500MB(均不含安装的包);conda-forge的包是预编译的,安装科学计算库时反而省事。

场景推荐可以这样落地:Web开发(Django/Flask)用venv+pip,依赖纯Python且轻量;数据科学用conda管理C扩展依赖;深度学习用conda处理CUDA等系统依赖;微服务用venv配合Docker容器化;工具开发用venv+pipx隔离CLI;团队协作的关键不是选哪个,而是统一工具并锁定依赖。

五、把环境初始化写进脚本

手工敲命令容易漏步骤,初始化脚本要加set -e让错误立即中断:
  1. #!/bin/bash
  2. set -e
  3. echo "创建虚拟环境..."
  4. python3.12 -m venv .venv
  5. echo "激活虚拟环境..."
  6. source .venv/bin/activate
  7. echo "升级pip..."
  8. pip install --upgrade pip
  9. echo "安装依赖..."
  10. pip install -r requirements/dev.txt
  11. echo "安装pre-commit hooks..."
  12. pre-commit install
  13. echo "环境初始化完成!"
复制代码

Windows批处理要用call调用激活脚本,否则后续命令仍在原环境执行:
  1. @echo off
  2. echo 创建虚拟环境...
  3. python -m venv .venv
  4. echo 激活虚拟环境...
  5. call .venv\Scripts\activate.bat
  6. echo 升级pip...
  7. python -m pip install --upgrade pip
  8. echo 安装依赖...
  9. pip install -r requirements\dev.txt
  10. echo 环境初始化完成!
复制代码

Makefile把常用操作收敛成目标,直接用环境内的解释器和pip,避免路径歧义:
  1. .PHONY: venv install test lint format clean
  2. VENV = .venv
  3. PYTHON = $(VENV)/bin/python
  4. PIP = $(VENV)/bin/pip
  5. venv:
  6.         python3.12 -m venv $(VENV)
  7.         $(PIP) install --upgrade pip
  8. install: venv
  9.         $(PIP) install -r requirements/dev.txt
  10. test:
  11.         $(PYTHON) -m pytest tests/ -v
  12. lint:
  13.         $(PYTHON) -m ruff check .
  14.         $(PYTHON) -m mypy src/
  15. format:
  16.         $(PYTHON) -m black .
  17.         $(PYTHON) -m ruff check --fix .
  18. clean:
  19.         rm -rf $(VENV)
  20.         rm -rf __pycache__
  21.         rm -rf .pytest_cache
复制代码

配合pyenv可以同时锁定解释器版本和环境:
  1. pyenv install 3.11.7
  2. pyenv versions
  3. pyenv global 3.12.1
  4. cd project/
  5. pyenv local 3.11.7
  6. python -m venv .venv
  7. source .venv/bin/activate
  8. pip install -r requirements.txt
复制代码

还可以用direnv在进入目录时自动激活,并顺带注入PYTHONPATH和数据库连接串:
  1. eval "$(direnv hook bash)"
  2. # .envrc
  3. source .venv/bin/activate
  4. export PYTHONPATH=$PWD/src:$PYTHONPATH
  5. export DATABASE_URL=postgresql://localhost/myapp
  6. direnv allow
复制代码

IDE侧,VS Code可以显式指定解释器并让终端自动激活:
  1. {
  2.   "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
  3.   "python.terminal.activateEnvironment": true,
  4.   "python.terminal.activateEnvInCurrentTerminal": true
  5. }
复制代码

PyCharm则通过Settings -> Project -> Python Interpreter -> Add Interpreter,选择Existing environment或新建环境。

六、常见故障与处理

PowerShell报“无法加载文件 Activate.ps1”,是执行策略问题,用Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser放开当前用户即可;提示activate脚本找不到,先确认路径是.venv/bin/activate还是.venv/Scripts/activate.bat;执行deactivate后仍显示在环境里,直接关掉终端重开。

pip装完包却没进虚拟环境,多半是pip指向了别的解释器。按顺序检查which pip、which python、pip --version,然后统一改用python -m pip安装;实在混乱就删掉环境重建,并用python -m pip install --upgrade pip刷新pip。

conda创建环境慢,可以换mamba(conda install mamba -n base -c conda-forge后用mamba create),或改用更小的micromamba,同时配置镜像源并开启strict渠道优先级。

venv创建的虚拟环境路径是写死的,整体移动目录后会失效,正确做法是重建;如果确实需要可迁移环境,可安装virtualenv并用virtualenv --always-copy .venv,但--relocatable并不总是可靠,不建议依赖。

七、更快的新选择:uv与pdm

uv用Rust编写、并行下载,官方口径是比pip快10到100倍,命令与pip高度兼容:
  1. pip install uv
  2. uv venv
  3. uv venv --python 3.12
  4. source .venv/bin/activate
  5. uv pip install requests
  6. uv pip install -r requirements.txt
  7. uv pip compile requirements.in -o requirements.txt
  8. uv pip sync requirements.txt
复制代码

pdm则偏向项目管理,初始化、加依赖、跑脚本、构建一条龙:
  1. pip install pdm
  2. pdm init
  3. pdm add requests
  4. pdm add -d pytest
  5. pdm install
  6. pdm run python main.py
  7. pdm run pytest
  8. pdm build
复制代码

八、结论

纯Python项目、Web服务、需要轻量和标准工具链时,venv配合requirements与Makefile脚本足够用;涉及科学计算、CUDA、C库或需要切换Python版本本身时,conda更省心,但要接受体积和解析耗时,并谨慎处理与pip的混用。团队层面真正的稳定来源是统一工具、统一依赖锁定方式,以及把环境初始化固化成可重复执行的脚本。
回复

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python虚拟环境venv与conda对比:命令配置与踩坑排查

楼主这个整理挺系统的,从场景出发再落到命令和目录结构,很适合当速查表用。venv 那块特别细,尤其是把 pyvenv.cfg 拿出来说排查解释器来源,这个点很多人踩过坑但不太会主动去看;还有 PowerShell 执行策略拦截 Activate.ps1,基本是 Windows 新机器必遇的问题,提前写出来能省不少时间。 说几个自己用下来的感受:`--system-site-packages` 虽然方便,但很容易让环境边界变模糊,后面排查依赖来源时会比较麻烦,建议只在明确知道要继承什么的时候开;另外 `pip freeze` 在装了大量包的环境里会带出一堆间接依赖,想看清直接装了啥还是 `pip list --not-required` 更直观。`.gitignore` 那段给得很实在,`__pycache__` 和 `.pytest_cache` 一起列上,团队协作时少很多无谓的 diff。 conda 部分只看到配置渠道和镜像就断了,有点意犹未尽,后面如果能把 environment.yml 的导出、复现以及和 pip 混用时的注意事项补上就更完整了。整体来说这篇对刚接触虚拟环境的人很友好,对老手也有几个能顺手收藏的命令。
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python虚拟环境venv与conda对比:命令配置与踩坑排查

楼主这部分写得很实在,尤其是把 pyvenv.cfg 拿出来讲排查解释器来源,这点很多人容易忽略。实际项目里遇到“明明激活了环境,pip 却装到全局”的情况,先看 which pip、再看 pip show 的 Location,基本就能定位,比反复重装环境省事。 补充几个自己踩过的坑:--system-site-packages 虽然方便继承系统包,但隔离性会打折,项目里一旦依赖版本冲突,排查起来反而更绕,非必要不建议开;--upgrade-deps 创建时会联网升级 pip 等核心依赖,内网或离线环境容易卡住,可以先用 --without-pip 建好再手动处理。Windows 下如果 PowerShell 执行策略不方便改,其实可以绕开激活脚本,直接用 .venv\Scripts\python.exe 和 .venv\Scripts\pip.exe 跑命令,CI 脚本里这样写也更稳。另外 .gitignore 那段建议再补上 .conda/ 和 *.egg-info/,团队里 venv 和 conda 混着用时,环境目录千万别提交。 conda 部分好像发到一半截断了,渠道优先级和 environment.yml 的导出导入还没看到,期待后续补上,特别是 strict 渠道优先级下混用 conda-forge 和 defaults 时依赖解析失败的排查思路。
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python虚拟环境venv与conda对比:命令配置与踩坑排查

这篇整理得很实在,venv 部分从创建参数、激活脚本到 pyvenv.cfg 和删除环境都覆盖了,尤其 which pip、where pip 以及 pip show 看 Location 的检查很实用,属于容易踩坑但平时容易忽略的点。conda 部分把渠道优先级、镜像和关闭 base 自动激活列出来也很清楚。不过正文到 conda config --s 好像截断了,后面 environment.yml 的导出复现和故障排查没看到,如果方便的话挺想继续看这部分,尤其是环境迁移和渠道冲突的处理。整体对照思路很好,适合收藏当速查。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-12 06:48 , Processed in 0.022767 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部