当前位置: 首页 > news >正文

Python虚拟环境实战:venv、conda与requirements.txt全解析

1. 为什么你写的 Python 代码在同事电脑上跑不起来?——虚拟环境不是“可选项”,是“生存线”

我第一次把写好的爬虫发给测试同事时,他回了我一句:“ImportError: No module named requests”。我愣了三秒,立刻截图发过去:“你 pip install requests 一下就行。”五分钟后,他回复:“pip 不是内部或外部命令。”我当场打开远程桌面,发现他电脑上压根没装 pip,Python 是从官网下载的 .exe 安装包,勾选了“Add Python to PATH”但没勾“Install pip”——这选项默认不勾。更讽刺的是,他系统里还躺着一个 Anaconda 自带的 Python,PATH 里两个 Python 路径打架,pip 指向了 conda 环境,而python命令却调用了 C:\Python39\python.exe。

这就是没有虚拟环境的真实代价:你不是在写 Python 代码,你是在和别人的操作系统、Python 版本、全局包管理器、PATH 环境变量打一场没有规则的混战。
“零基础入门虚拟环境”这句话背后藏着一个残酷事实:绝大多数 Python 新手根本不知道自己正在用“裸奔模式”开发。他们以为pip install就是安装,import xxx就是导入,直到某天pip install tensorflow把整个项目的numpy==1.19.5覆盖成numpy==2.0.0,导致pandas.read_csv()直接报错;或者pip install flask顺手升级了click,结果本地flask run正常,部署到服务器却提示click.echo() got an unexpected keyword argument 'err'——因为服务器上旧版click不支持err参数。

关键词里的venv、requirements.txt、pip,不是三个孤立工具,而是一套最小闭环生存系统:

  • venv是你的“隔离舱”,它不复制 Python 解释器,而是用符号链接(Windows 下是硬链接)快速创建一个干净、独立、与系统 Python 完全解耦的运行空间;
  • pip是这个舱内的“物资补给官”,它只管舱内仓库,绝不触碰舱外世界;
  • requirements.txt是你的“舱内物资清单”,它精确记录每一件物资的名称和版本号,确保下次重建隔离舱时,一模一样。

你不需要懂sys.path如何被修改,也不必研究site-packages的加载顺序。你只需要记住:只要没激活虚拟环境,你就没资格说“我的 Python 环境配置好了”。这不是仪式感,是工程底线。哪怕你只是写一个 10 行的脚本处理 Excel 表格,也该为它建个venv。因为下一次你可能要加一行import openpyxl,而openpyxl依赖的et-xmlfile又会悄悄覆盖掉你另一个项目里正在用的lxml==4.9.3。混乱从来不是从大型项目开始的,它始于第一个pip install没加-i镜像源、没加--user、也没进虚拟环境的那一刻。

2. venv 与 conda:别再被“哪个更好”困住——先搞懂它们解决的根本问题不同

搜索热词里反复出现 “anaconda 创建虚拟环境”、“conda 创建 python 虚拟环境”、“miniforge 虚拟环境”,甚至还有人问 “conda 和 venv 能不能一起用”。这说明一个普遍误区:把 venv 和 conda 当成同一类工具的两种品牌,试图做“二选一”。实际上,它们连“赛道”都不一样。

我们来拆解最核心的差异点:venv 管理的是 Python 包(packages),conda 管理的是软件包(packages + binaries + environments)

  • python -m venv myenv创建的环境,本质是:

    • 复制一份python.exe(或python可执行文件)的引用;
    • 创建一个空的site-packages文件夹;
    • 修改activate.bat/activate.sh,让PATH临时指向这个新bin/Scripts目录;
    • 它完全不碰 Python 解释器本身——你用什么版本的 Python 安装的 venv,环境里就是什么版本,无法跨版本切换。
  • conda create -n myenv python=3.11创建的环境,本质是:

    • 从 conda 渠道(如 defaults, conda-forge)下载并解压一个完整、预编译的 Python 3.11 解释器二进制包;
    • 同时下载所有依赖库(如openssl,zlib,sqlite)的二进制文件,一并放进环境目录;
    • 它管理的是整个“运行时栈”,包括 C 库、Fortran 编译器、甚至 R 语言解释器。

所以,当你看到 “conda 删除虚拟环境” 或 “conda 虚拟环境部署 facefusion”,你就该明白:facefusion 这类项目重度依赖 OpenCV、ONNX Runtime、CUDA 驱动等底层二进制组件,它们有复杂的 ABI 兼容性要求。pip install opencv-python下载的是 wheel 包,里面打包了预编译的.so.dll,但它只保证与当前 Python 版本兼容,不保证与你的显卡驱动、CUDA 版本匹配。而conda install opencv下载的是 conda-forge 编译的包,它明确声明了所依赖的cudatoolkit=11.8cudnn=8.6,conda 会自动帮你拉取匹配的版本,避免ImportError: libcudnn.so.8: cannot open shared object file这种经典报错。

那新手该选哪个?答案很务实:

  • 如果你学的是Web 开发(Django/Flask)、数据分析(pandas/numpy)、自动化脚本、爬虫无脑用venv。理由极其简单:Python 官方内置,无需额外安装,学习成本为零,pip生态无缝对接,requirements.txt标准统一。你用pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ flask,它就老老实实装 flask,不会顺手给你换掉系统 Python。
  • 如果你做的是AI/ML(PyTorch/TensorFlow)、科学计算(SciPy)、需要 CUDA 加速、或必须用特定 Fortran 编译器的数值模拟直接上 conda/miniforge。因为它能一次性解决“Python 解释器 + C/C++ 运行时 + GPU 驱动库 + 科学计算 BLAS 库”的全栈兼容性问题。conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia这一条命令,背后是 conda 在数十个二进制包中精准匹配 ABI 版本,这是 pip 做不到的。

提示:venvconda并非互斥。你可以用 conda 创建一个纯净的 Python 环境(conda create -n py311 python=3.11),然后在这个 conda 环境里再用python -m venv myproject_env创建子环境。这种“conda 管 Python 版本,venv 管项目依赖”的嵌套模式,在大型团队中很常见——conda 解决基础运行时一致性,venv 解决项目级依赖隔离。

3. 从零创建、激活、使用虚拟环境:Windows/macOS/Linux 三端实操细节全解析

很多教程写“打开终端,输入python -m venv myenv”,然后就跳到source myenv/bin/activate。但新手卡在第一步:“终端在哪?”、“python 命令不存在?”、“venv 文件夹创建后是空的?”这些不是小问题,是真实阻碍。下面我按操作系统,把每个“看似简单”的步骤掰开揉碎,告诉你为什么这么操作、哪里容易出错、以及出错后怎么救。

3.1 Windows 系统:CMD、PowerShell、Git Bash 的激活方式完全不同

Windows 上最大的坑,就是PowerShell 默认禁用脚本执行策略。当你在 PowerShell 里输入myenv\Scripts\activate.bat,它会报错:“无法加载文件 myenv\Scripts\activate.ps1,因为在此系统中禁止执行脚本。” 这不是你的环境坏了,是 PowerShell 的安全策略在起作用。

正确做法分三步:

  1. 确认 Python 已正确安装并加入 PATH

    • Win+R,输入cmd回车;
    • 输入python --version,应显示Python 3.x.x
    • 输入where python,应返回类似C:\Users\YourName\AppData\Local\Programs\Python\Python311\python.exe的路径;
    • 如果提示“不是内部或外部命令”,请重新安装 Python,务必勾选 “Add Python to PATH”(安装器最下方那个小勾选框,很多人忽略)。
  2. 创建虚拟环境(推荐用 CMD,避开 PowerShell 权限问题)

    # 进入你的项目文件夹,比如 D:\myproject cd /d D:\myproject # 创建名为 "venv" 的虚拟环境(名字随意,但 "venv" 是行业惯例) python -m venv venv

    执行后,你会看到项目目录下多了一个venv文件夹。它不是空的!里面包含:

    • venv\Scripts\:存放python.exe,pip.exe,activate.bat(CMD 用),Activate.ps1(PowerShell 用);
    • venv\Lib\site-packages\:初始为空,pip install后包会装在这里;
    • venv\pyvenv.cfg:配置文件,记录 base Python 路径和是否 include system site-packages。
  3. 激活环境(关键!不同终端用不同命令)

    • CMD 用户venv\Scripts\activate.bat
    • PowerShell 用户:先临时绕过策略(仅本次会话有效):
      Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser venv\Scripts\Activate.ps1
    • Git Bash 用户source venv/Scripts/activate(注意是正斜杠/,且activate.bat.ps1后缀)

注意:激活成功后,命令行提示符前会出现(venv)字样,例如(venv) C:\myproject>这是唯一可靠的激活成功标志。如果没看到(venv),说明没激活,后续所有pip install都会装到全局环境!

3.2 macOS/Linux 系统:权限、Shell 类型、路径分隔符的隐藏雷区

macOS 和 Linux 用户常遇到的问题是:source venv/bin/activate后,pip命令还是找不到,或者python版本没变。根源往往在 Shell 类型和 PATH 设置。

  1. 确认你的默认 Shell

    echo $SHELL # 输出 /bin/zsh(macOS Catalina+ 默认)或 /bin/bash

    如果你用的是 zsh,但教程教的是 bash 的source命令,它依然有效,因为source是 POSIX 标准命令。但如果你用的是 fish shell,source就不工作,得用source venv/bin/activate.fish

  2. 创建与激活(标准流程)

    # 进入项目目录 cd ~/Projects/myproject # 创建虚拟环境(注意:Linux/macOS 用 "venv" 文件夹名,路径分隔符是 "/") python3 -m venv venv # 激活(zsh/bash 都适用) source venv/bin/activate

    激活后,which python应返回~/Projects/myproject/venv/bin/pythonwhich pip返回同目录下的pip

  3. 常见故障排查

    • /usr/bin/python: no module named venv:说明你用的是系统自带的 Python 2.7(macOS 10.14 及更早版本)。解决方案:用 Homebrew 安装 Python 3:brew install python3,然后用python3 -m venv venv
    • 激活后pip仍报错 “command not found”:检查venv/bin/目录下是否有pip文件(ls -l venv/bin/pip)。如果没有,说明创建失败,删除venv文件夹重试;
    • pip install报错 “Permission denied”:绝对不要加sudo!这会破坏虚拟环境的隔离性。正确做法是确保你对venv文件夹有读写权限:chmod -R u+rw venv

3.3 统一验证法:三步确认你的虚拟环境真正“活”了

无论哪个系统,激活后必须做这三件事,缺一不可:

  1. 检查 Python 解释器路径

    which python # macOS/Linux where python # Windows CMD # 输出必须是项目目录下的 venv/bin/python 或 venv\Scripts\python.exe
  2. 检查 pip 是否指向虚拟环境内

    which pip pip --version # 输出应显示 pip 位置在 venv 内,且版本号后带 "(from venv)"
  3. 检查 site-packages 是否为空(初始状态)

    python -c "import site; print(site.getsitepackages())" # 输出应是一个路径列表,第一个路径就是 venv/lib/python3.x/site-packages/ # ls -l venv/lib/python3.x/site-packages/ # 应只有 __pycache__ 和 easy-install.pth 等基础文件

提示:如果以上三步任一失败,请立即停手。不要继续pip install。先删除整个venv文件夹,重新python -m venv venv,再严格按上述步骤激活。虚拟环境的“洁净度”比速度重要一百倍。

4. requirements.txt:不是备份文件,是项目可复现性的法律契约

很多新手把requirements.txt当成一个“顺便生成的清单”,pip freeze > requirements.txt一下就完事。但当他们把这份文件发给同事,同事pip install -r requirements.txt后,项目依然报错,于是抱怨 “requirements.txt 没用”。真相是:他们生成的是一份“污染清单”,而不是“契约清单”。

pip freeze的本质是:列出当前环境中所有已安装包及其精确版本号(包括你无意中装的、依赖传递带进来的、甚至系统级的包)。它不区分“项目必需”和“偶然存在”。比如你为了调试装了个jupyterpip freeze就会把它写进去;你用pip install flask时,flask依赖Werkzeug,Jinja2,itsdangerous,这些也会被列出来。但requirements.txt的使命,是定义“这个项目启动所需的最小依赖集合”,而不是“这个环境里有什么”。

4.1 正确生成 requirements.txt 的三种场景与对应方法

场景问题推荐方法命令示例原理
全新项目,手动安装依赖你只装了flask,requests,sqlalchemy,但pip freeze会列出 20+ 个包pipreqs工具pip install pipreqs
pipreqs ./ --encoding=utf8
pipreqs扫描项目 Python 文件中的import语句,只生成实际被代码引用的包,忽略传递依赖和调试工具
已有项目,需精确控制版本flask的最新版 2.3.0 有 breaking change,你只想锁定flask==2.2.5手动编辑 +pip install -e .创建setup.py,在install_requires中写flask==2.2.5
pip install -e .
-e模式(editable install)让 pip 把当前目录当作一个可安装包,setup.py中的依赖声明才是权威来源
生产环境部署,需绝对稳定你希望numpy永远是1.24.3,不接受任何1.24.x的微更新pip freeze+ 人工精简pip freeze > requirements.in
手动删掉jupyter,ipython,wheel等非必需项
pip install -r requirements.in
requirements.in是“原料清单”,requirements.txt是“成品清单”。部署时用pip install -r requirements.txt,确保字节级一致

4.2 requirements.txt 的黄金书写规范(避坑指南)

一份专业的requirements.txt必须遵守以下四条铁律:

  1. 每行一个包,格式为package_name==version

    • requests==2.31.0
    • requests >= 2.30.0(版本浮动会导致不可复现)
    • requests(无版本号,下次pip install可能装 3.0.0)
  2. 使用#注释说明用途

    # Web 框架核心 flask==2.2.5 # 数据库 ORM sqlalchemy==2.0.23 # 用于处理 Excel 文件 openpyxl==3.1.2
  3. 将开发依赖(dev dependencies)分离

    • 创建requirements-dev.txt,内容如:
      # 开发时用,生产环境不需 pytest==7.4.3 black==23.10.1 mypy==1.7.1
    • 安装时:pip install -r requirements.txt(生产依赖) +pip install -r requirements-dev.txt(开发依赖)
  4. 指定镜像源,避免国内用户安装失败

    • requirements.txt第一行添加:
      -i https://pypi.tuna.tsinghua.edu.cn/simple/
    • 或者全局配置:pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/

实操心得:我曾维护一个 50 人的数据科学项目,某次pip freeze > requirements.txt后,一位同事的matplotlib升级到了 3.8.0,导致所有plt.show()图形窗口无法关闭。后来我们强制规定:所有requirements.txt必须由pipreqs生成,并在 CI 流水线中加入校验步骤——pipreqs扫描结果必须与requirements.txt完全一致,否则构建失败。这成了我们项目的“法律契约”。

5. 真实排错链路:从 “pip 不是内部或外部命令” 到 “成功运行第一个 Flask 应用”

现在,我们把前面所有知识点串起来,走一遍最典型的新手排错全流程。这不是假设,而是我每天在技术群、Stack Overflow 上看到的真实案例。

5.1 故障现场还原:用户提问 “pip : 无法将‘pip’项识别为 cmdlet、函数、脚本文件或可运行程序的名称”

用户环境:Windows 11,Python 3.11 从官网下载安装,勾选了 “Add Python to PATH”,但没勾 “Install pip”。他打开 PowerShell,输入pip --version,报错如题。

我的排查思路(不是直接给答案,而是展示如何思考):

  1. 第一层:确认 pip 是否真的存在?

    • where pip(CMD)或Get-Command pip(PowerShell)→ 返回空,证明 pip 可执行文件确实没生成;
    • dir "C:\Users\YourName\AppData\Local\Programs\Python\Python311\"→ 查看目录下是否有Scripts\pip.exe
    • 结果:Scripts文件夹里只有python.exe,pythonw.exe, 没有pip.exe
  2. 第二层:为什么 pip 没安装?

    • 回顾 Python 官网安装器界面:有一个独立的复选框 “Install pip”,它和 “Add Python to PATH” 是两个独立选项;
    • 用户只勾了后者,忘了前者。这是 Python 安装器的 UX 设计缺陷,也是新手最高频的坑。
  3. 第三层:如何修复?

    • 方案 A(推荐):重装 Python,这次两个都勾
    • 方案 B(应急):手动安装 pip
      • 下载get-pip.py(https://bootstrap.pypa.io/get-pip.py);
      • 在 CMD 中运行:python get-pip.py
      • where pip应返回C:\Users\YourName\AppData\Local\Programs\Python\Python311\Scripts\pip.exe

5.2 进阶故障:激活虚拟环境后,pip install flask成功,但python app.py报错 “ModuleNotFoundError: No module named 'flask'”

用户环境:已成功创建并激活venvwhich pip指向venv/Scripts/pippip install flask显示 “Successfully installed flask-2.2.5”,但运行python app.py时仍报错。

排查链路:

  1. 确认python命令是否真的调用虚拟环境内的解释器?

    • where python→ 返回C:\Python311\python.exe(系统 Python),而非venv\Scripts\python.exe
    • 原因:Windows 上,activate.bat只修改了PATH,但python命令的优先级可能被系统 PATH 中更靠前的 Python 覆盖;
    • 验证venv\Scripts\python.exe app.py→ 成功!证明问题出在python命令的解析上。
  2. 根本解决方案:永远用python而不是py或系统python

    • 在激活状态下,python命令会被venv\Scripts\目录下的python.exe拦截;
    • 但如果 PATH 中有多个 Python,保险起见,在项目根目录下,直接运行venv\Scripts\python.exe app.py
    • 或者,在 PyCharm/VSCode 中,将 Python 解释器路径手动设置为venv\Scripts\python.exe

5.3 终极验证:用 10 行代码跑通 Flask,完成闭环

现在,我们用一个最简 Flask 应用,验证整个虚拟环境链路是否真正打通:

  1. 在已激活的venv中,创建app.py

    from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from Virtual Environment!" if __name__ == '__main__': app.run(debug=True)
  2. 安装 Flask 并运行:

    # 确保已激活 (venv) pip install flask==2.2.5 python app.py
  3. 访问http://127.0.0.1:5000,看到 “Hello from Virtual Environment!”

    • ✅ 成功!这意味着:
      • Python 解释器来自venv
      • flask包安装在venv\Lib\site-packages\
      • import flaskvenv加载,而非全局;
      • 整个依赖链路干净、隔离、可复现。

最后分享一个小技巧:在 VSCode 中,按Ctrl+Shift+P(Windows)或Cmd+Shift+P(macOS),输入 “Python: Select Interpreter”,然后选择你项目下的venv\Scripts\python.exe。VSCode 会自动在底部状态栏显示(venv),并且集成终端(Terminal)会自动激活该环境。这是目前最丝滑的开发体验,比手动activate高效十倍。

我第一次用虚拟环境跑通 Flask 时,盯着浏览器里那行 “Hello from Virtual Environment!” 看了足足一分钟。不是因为代码多牛,而是因为我知道,从此以后,我的每一个pip install,都不再是向混沌宇宙投掷一颗石子,而是在亲手搭建一座可控、可预测、可交付的数字方舟。这,就是 Python 工程化的起点。

http://www.jsqmd.com/news/1071498/

相关文章:

  • Windows本地AI开发环境:WSL2+Ubuntu24.04+Ollama+1panel+copaw全链路部署
  • Claude Code Mac安装指南:CLI工具本质与多模型配置实战
  • Windows本地部署飞书数字员工:PowerShell一键启用AI自动化
  • OpenClaw:可编程命令行技能调度器,统一管理网关与CLI自动化
  • MPC860 PCMCIA控制器寄存器详解与中断处理实战
  • MATLAB ODE求解:从醉汉游走到卫星轨道的动态系统建模与仿真
  • Claude Code v2.3.1本地运行Opus 4.8全指南
  • Spring AI vs Spring AI Alibaba:Java AI工程化选型指南
  • eBPF+LSM技术实战:构建Linux内核级安全监控与防护系统
  • SQL Server 2022手动安装实战:路径、混合模式与SSMS独立部署
  • Wireshark实战解析IEC 101规约:从抓包到遥控遥信报文深度分析
  • Agent Skills:从技能文档到行为契约的工程化实践
  • OpenCLAW飞书云原生集成:零代码AI能力嵌入工作流
  • Wireshark抓包分析核心:OSI分层过滤与TCP三次握手精解
  • MATLAB实现数独求解器:融合回溯法与候选数法的算法实践
  • 国产大模型落地实战:从智能体编排到全栈国产化适配
  • 密码掩码设计全解析:从安全原理到前端实现的最佳实践
  • Sora内测申请实战指南:从资格获取到高效应用全解析
  • MPC860 ATM调度与中断机制:硬件原理与实战配置详解
  • MPC8641D PCIe控制器错误捕获与配置空间访问机制详解
  • 教学辅助问答系统:基于SpringBoot+Vue的知识引擎设计
  • 长上下文大模型在金融招股书理解中的实战突破
  • Llama4应用构建:基于DLAI范式的可监控生产流水线
  • 从实战视角解析学生方程式大赛:线控刹车标定与数据采集系统应用
  • MPC8572E DMA控制器工作模式详解:从基础到高级的性能优化实践
  • CTF实战:从流量分析到AES解密的Misc综合解题思路
  • 用 Nacos 3.2 构建企业级 Skills Registry
  • 安卓APP逆向实战:从静态分析到动态验证的完整流程解析
  • 科学计算代码现代化重构:从Python 2祖传算法到可维护工程实践
  • MATLAB eigshow 交互式学习:特征值与奇异值分解的几何可视化