Python虚拟环境是一个自包含的目录,包括自己的Python解释器和一组已安装的包,与系统范围的Python安装隔离。使用虚拟环境让每个项目可以维护自己的依赖项,而不会影响同一台机器上的其他项目。
本指南介绍如何使用venv(Python 3内置)和virtualenv(流行的第三方替代方案)在Linux和macOS上创建和管理虚拟环境。
快速参考
任务 命令 安装venv支持 (Ubuntu, Debian) sudo apt install python3-venv 创建环境 python3 -m venv venv 激活 (Linux / macOS) source venv/bin/activate 取消激活 deactivate 安装包 pip install package-name 安装特定版本 pip install package==1.2.3 列出已安装包 pip list 保存依赖 pip freeze > requirements.txt 从requirements文件安装 pip install -r requirements.txt 使用特定Python版本创建 python3.11 -m venv venv 创建时包含系统包 python3 -m venv --system-site-packages venv 创建时升级核心venv依赖 python3 -m venv --upgrade-deps venv 安装virtualenv pipx install virtualenv 将pipx工具添加到PATH pipx ensurepath 全局安装CLI工具 pipx install <tool>
什么是Python虚拟环境?
当你使用pip install全局安装一个包时,它对系统上的每个Python脚本都可用。当两个项目需要同一个库的不同版本时,这就成了问题。例如,一个项目要求requests==2.28.0,而另一个项目要求requests==2.31.0,两者无法同时全局安装。
虚拟环境通过为每个项目提供独立的包存储空间来解决这个问题。激活环境后,它会将其bin/目录添加到你的PATH前面,这样python和pip就会解析到环境内的版本,而不是系统范围的版本。
externally-managed-environment错误
在Ubuntu 23.04及更高版本以及Debian 12及更高版本上,系统Python根据PEP 668被标记为外部管理。如果你在虚拟环境外运行pip install,命令会报错停止:
error: externally-managed-environment
× This environment is externally managed
╰→ To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
这是故意设计的,不是bug。发行版拥有系统Python,允设pip写入可能会破坏依赖特定库版本的打包工具。你可以使用--break-system-packages强制安装,但更安全的做法是本指南介绍的:创建虚拟环境并在其中安装。
安装venv
venv模块随Python 3一起发行,在大多数系统上无需单独安装。在Ubuntu和Debian上,该模块被单独打包:
sudo apt install python3-venv
在Fedora、RHEL及其衍生版本上,venv默认包含在Python包中。
创建环境前先验证Python版本:
python3 --version
创建虚拟环境
进入你的项目目录并运行:
python3 -m venv venv
第二个venv是将被创建的目录名称。常见的命名习惯是venv或.venv。该目录包含Python二进制文件或符号链接、激活脚本、pip和用于安装包的site-packages目录。
要在特定位置创建环境而非当前目录:
python3 -m venv ~/projects/myproject/venv
venv常用参数
python3 -m venv接受几个有用的参数:
--system-site-packages — 让环境可以看到系统Python中安装的包。当重量依赖更容易通过系统包管理器安装时很有用。
--without-pip — 跳过捆绑的pip。你可以稍后用python -m ensurepip安装pip。
--copies — 将Python二进制文件复制到环境中而不是创建符号链接。默认使用符号链接,速度更快但将环境绑定到原始解释器路径。
--upgrade-deps — 创建后立即将核心venv依赖项(如pip)升级到PyPI上的最新版本。
--upgrade — 当系统Python升级时,使用新的Python版本重建环境。运行python3 -m venv --upgrade /path/to/existing/venv。
开始新项目时的常见组合用法:
python3 -m venv --upgrade-deps myenv
激活虚拟环境
使用环境前需要先激活它。在Linux和macOS上:
source venv/bin/activate
如果你使用fish或csh,请同样目录下的activate.fish或activate.csh。在Windows上,激活脚本位于venv\Scripts\activate(cmd)或venv\Scripts\Activate.ps1(PowerShell)。
激活后,shell提示符会显示环境名称:
(venv) user@host:~/myproject$
此时python和pip指向虚拟环境内的版本,而非系统范围的版本。
要取消激活并返回系统Python:
deactivate
pyvenv.cfg文件
每个环境根目录包含一个pyvenv.cfg文件,记录了构建环境所用的解释器、Python版本和系统站点包控制标志:
home = /usr/bin include-system-site-packages = false version = 3.12.3
如果需要在不重建环境的情况下切换系统包访问权限,将include-system-site-packages编辑为true。其他设置不应手动修改,因为环境重建时会重新生成它们。
安装包
激活环境后,像平时一样使用pip安装包。
pip install requests
安装特定版本:
pip install requests==2.31.0
列出当前环境安装的所有包:
pip list
此处安装的包与系统及其他虚拟环境完全隔离。
使用requirements.txt管理依赖
与他人分享项目或部署到另一台机器时,需要一种方式来复现相同的包版本。常规做法是将所有依赖保存到requirements.txt文件:
pip freeze > requirements.txt
该文件列出每个已安装的包及其精确版本:
certifi==2024.2.2 charset-normalizer==3.3.2 idna==3.6 requests==2.31.0 urllib3==2.2.1
在新环境中从文件安装所有包:
pip install -r requirements.txt
这是在不同机器或CI/CD管线中复现环境的标准工作流。
使用特定Python版本
默认情况下,python3 -m venv使用系统默认的Python 3版本。如果安装了多个Python版本,可以指定使用哪个:
python3.11 -m venv venv
这将基于Python 3.11创建环境,无论系统默认版本是什么。检查可用版本:
python3 --version
python3.11 --version
virtualenv:venv的替代方案
virtualenv是一个比venv更早出现的第三方包,提供额外的环境创建功能。使用pipx作为隔离的命令行工具安装:
pipx install virtualenv
使用virtualenv创建和激活环境的方式相同:
virtualenv venv
source venv/bin/activate
使用特定的Python解释器:
virtualenv -p python3.11 venv
当你频繁创建环境并希望利用其缓存的种子包、解释器发现功能或编程API和插件系统时,选择virtualenv。与venv不同,virtualenv可以通过版本规范符查找已安装的解释器,并且独立于Python发行版本更新。
对于大多数现代Python 3项目,venv已经足够,且无需安装。
uv:更快的现代替代方案
uv是一个用Rust编写的更新的Python包管理器,包含内置的venv命令。它在环境创建和包安装方面明显快于venv和virtualenv。
使用uv创建环境:
uv venv myenv
source myenv/bin/activate
uv在CI中安装速度很重要时成为常见选择,但venv在希望零额外依赖时仍是最佳默认选择。
使用pipx安装工具
有时你希望全局安装一个Python工具,让它始终可用,但不污染系统Python或创建项目级venv。pipx通过为每个工具提供私有的虚拟环境来解决这个问题,你不需要激活它。
安装pipx并用它安装如httpie等CLI工具:
sudo apt install pipx
pipx ensurepath
pipx install httpie
运行pipx ensurepath后重启shell,以使pipx安装的命令在PATH上可用。
用venv管理项目依赖,用pipx管理命令行工具。两者解决不同的问题。
从版本控制中排除环境
虚拟环境目录不应提交到版本控制。它体积大、与机器相关且可从requirements.txt完全复现。将其添加到.gitignore:
echo "venv/" >> .gitignore
如果环境命名为.venv,则将.venv/添加到.gitignore。
常见问题排查
执行python3 -m venv venv报错"No module named venv"
在Ubuntu和Debian上,venv模块不包含在基础Python包中。使用sudo apt install python3-venv安装,然后重试。
pip install将包安装到全局而非环境中
环境未激活。先运行source venv/bin/activate。可以通过which pip验证,它应指向venv/目录内的路径。
激活后python仍指向环境外
环境可能未激活,或shell缓存了旧的命令路径。运行source venv/bin/activate,然后检查which python和which pip。在Bash或Zsh中,如果shell仍解析旧路径,运行hash -r。
移动或重命名目录后环境损坏
虚拟环境包含Python解释器的绝对路径。移动或重命名目录会使这些路径失效。删除目录并在新位置重建环境,然后从requirements.txt重新安装。
常见问题
venv和virtualenv有什么区别?
venv是Python 3标准库模块,无需安装。virtualenv是第三方工具,具有缓存环境创建、解释器发现、编程API和插件支持。对于基本环境需求的新Python 3项目,推荐使用venv。
为什么pip说环境是externally managed?
Ubuntu 23.04及更高版本和Debian 12及更高版本根据PEP 668将系统Python标记为外部管理,因此pip拒绝向其安装。创建虚拟环境并在其中安装。仅在你了解后果时才使用--break-system-packages。
应该将虚拟环境提交到git吗?
不应该。将venv/(或.venv/)添加到.gitignore,只提交requirements.txt。任何人结账后可以用pip install -r requirements.txt重新创建环境。
每个项目都需要虚拟环境吗?
强烈建议。没有隔离环境,为一个项目安装或升级包可能会破坏另一个。创建虚拟环境的开销很小。
pip freeze和pip list有什么区别?
pip list以人类可读格式显示已安装包。pip freeze以requirements.txt格式(package==version)输出,适合与pip install -r配合使用。
能否使用与系统默认不同的Python版本创建虚拟环境?
可以。创建环境时传递所需解释器的路径:python3.11 -m venv venv。环境将使用该解释器执行python和pip命令。
对于black、ruff、httpie等CLI工具应该用venv还是pipx?
使用pipx。它为每个工具提供私有环境,安装不会冲突,且你无需激活任何东西就能运行工具。将venv留给项目导入的库。
pyvenv.cfg是做什么的?
它是每个venv根目录的小配置文件。记录环境构建所用的解释器、Python版本以及环境是否可以看到系统站点包。include-system-site-packages标志是通常需要手动编辑的唯一设置。
总结
虚拟环境是管理Python项目依赖的标准方式。使用python3 -m venv venv创建,source venv/bin/activate激活,并使用pip freeze > requirements.txt捕获依赖项。