Ubuntu下Python虚拟环境搭建:venv、virtualenv与pipenv对比与实践
1. 项目概述:为什么我们需要Python虚拟环境?
如果你在Ubuntu上写过Python,大概率遇到过这样的场景:项目A需要Django 3.2,项目B需要Django 4.2,而系统全局安装的包版本只有一个。更头疼的是,当你尝试用pip install安装一个新包时,可能会因为依赖冲突导致整个环境崩溃,甚至影响到系统自带的Python工具。这种“依赖地狱”是每个Python开发者迟早要面对的挑战。虚拟环境,就是为了解决这个问题而生的隔离工具,它允许你为每个项目创建一个独立的Python运行环境,包括独立的解释器、包安装目录和脚本路径。这样,项目之间的依赖就完全隔离开了,互不干扰。
在Ubuntu这样的Linux发行版上,系统本身可能依赖特定版本的Python包(比如apt管理的python3-requests),直接使用pip安装或升级包很容易破坏系统稳定性。因此,在Ubuntu下使用虚拟环境不仅是开发的最佳实践,更是保护系统环境安全的必要措施。今天,我们就来深入聊聊Ubuntu系统下三种主流的Python虚拟环境搭建方法:venv、virtualenv和pipenv。我会结合多年的运维和开发经验,告诉你它们各自的适用场景、核心差异以及我踩过的那些坑,帮你找到最适合自己工作流的那一款。
2. 核心工具对比与选型逻辑
在开始动手之前,我们先得搞清楚这三者到底是什么,以及为什么会有这么多选择。这绝不是简单的“哪个更新就用哪个”,而是关乎项目规模、团队协作和个人习惯的综合性决策。
2.1 官方钦定与轻量之选:venv
venv是Python 3.3版本之后内置的标准库模块。这意味着,只要你安装了Python 3.3或更高版本,就可以直接使用它,无需任何额外安装。它的设计哲学是“简单够用”,只提供最核心的虚拟环境创建与管理功能。
核心优势:
- 零依赖:作为标准库的一部分,开箱即用,无需
pip install任何东西。 - 与系统集成好:在Ubuntu上,它默认使用系统的
python3解释器来创建环境,行为最可预测。 - 轻量快速:创建环境的速度通常是最快的,因为功能纯粹。
主要局限:
- 功能相对基础:它只负责创建环境。环境的激活、依赖包的管理(
pip install)、依赖记录(生成requirements.txt)都需要你手动或用其他工具链配合完成。 - 无法指定Python解释器版本:
venv只能基于当前调用的python3命令对应的版本来创建环境。如果你想在Ubuntu 22.04(默认Python 3.10)上创建一个Python 3.8的环境,venv本身做不到,需要你先安装Python 3.8。
注意:在Ubuntu上,有时直接运行
python命令会指向Python 2(如果系统仍保留的话),而python3才指向Python 3。使用venv时,务必明确使用python3 -m venv来调用。
适用场景:适合小型、临时的脚本或项目;当你需要快速创建一个干净的环境进行测试,且不需要复杂依赖管理时;也适合作为学习虚拟环境概念的第一站。
2.2 历史悠久且功能强大:virtualenv
virtualenv是虚拟环境工具的“老前辈”,在venv出现之前,它是事实上的标准。它是一个第三方包,需要通过pip安装。虽然venv借鉴了它的设计,但virtualenv在某些方面仍然更强大、更灵活。
核心优势:
- 支持多版本Python:这是它与
venv最关键的区别。你可以先通过apt或pyenv安装多个Python版本(如3.8, 3.9, 3.10),然后使用virtualenv -p参数指定任意一个版本来创建虚拟环境。 - 兼容性极广:支持Python 2和Python 3的所有主流版本,对于需要维护遗留项目的场景不可或缺。
- 可定制性更强:提供更多命令行参数,可以精细控制环境的行为,比如是否继承系统站点的包(
--system-site-packages)。
主要局限:
- 需要额外安装:虽然安装简单(
pip install virtualenv),但毕竟多了一步。 - 与
venv命令略有不同:习惯了venv的命令后,切换到virtualenv需要适应一下(例如,venv用python3 -m venv myenv,而virtualenv通常直接用virtualenv myenv)。
适用场景:需要为项目指定特定Python版本(尤其是非系统默认版本)时;需要兼容Python 2的老项目;当你需要更高级的环境定制选项时。
2.3 依赖管理的集大成者:pipenv
pipenv的目标不仅仅是创建一个虚拟环境,它旨在成为“Python官方推荐的包管理工具”。它融合了pip(包安装)和virtualenv(环境管理),并引入了类似npm或yarn的依赖锁定文件(Pipfile.lock),旨在提供一站式的、更现代化的项目管理体验。
核心优势:
- 自动创建和管理虚拟环境:你不需要显式地先创建环境。在项目目录下执行
pipenv install,它会自动检查是否有虚拟环境,没有则创建一个,然后安装包。 - 革命性的依赖管理:使用
Pipfile(替代requirements.txt)来声明依赖,区分生产依赖([packages])和开发依赖([dev-packages])。Pipfile.lock则锁定所有依赖及其次级依赖的确切版本,确保环境完全可重现。 - 更安全的依赖解析:其依赖解析算法被认为比传统的
pip更健壮,能更好地处理复杂的依赖关系图。 - 便捷的命令:
pipenv shell进入环境,pipenv run直接执行命令,pipenv graph查看依赖树,非常人性化。
主要局限:
- 性能与复杂性:早期的
pipenv因依赖解析速度慢而备受批评,虽然后期有改善,但在依赖数量极大的项目中,速度可能仍不如pip+venv。它的抽象层级更高,出问题时调试可能更复杂。 - 社区分歧:尽管曾获官方推荐,但其发展一度停滞,且并未完全取代
pip+virtualenv/venv的工作流,社区中仍有大量项目使用传统方式。 - 学习新概念:需要理解
Pipfile和Pipfile.lock,对于习惯了requirements.txt的开发者有转换成本。
适用场景:全新的、特别是涉及Web开发(如Django, Flask)的应用程序项目;追求依赖锁定和确定性构建的团队协作场景;喜欢一体化、现代化工具链的开发者。
我的选型心得:
- 求快、求简单、做一次性任务:用
venv。 - 需要特定Python版本,或项目环境复杂:用
virtualenv。 - 启动一个严肃的、需要长期维护和团队协作的新项目:尝试
pipenv,体验其一体化管理的便利。 - 最稳妥、最通用的方案:
virtualenv+pip+requirements.txt。这套组合历经考验,几乎所有服务器都支持,教程也最多,是最不会出错的选择。我个人的生产环境也主要采用这套。
3. 三种方法的详细搭建步骤与实操要点
理论说完了,我们直接上干货。以下操作均假设你使用的是Ubuntu 22.04 LTS或更高版本,并已安装好python3和pip。
3.1 使用 venv 搭建虚拟环境
步骤1:确认Python3和pip打开终端,输入以下命令:
python3 --version pip3 --version确保有版本号输出。如果没有pip3,可以安装:sudo apt update && sudo apt install python3-pip -y。
步骤2:创建虚拟环境假设你的项目目录是~/my_venv_project。
cd ~ mkdir my_venv_project && cd my_venv_project # 使用当前系统的python3解释器创建名为 .venv 的虚拟环境目录 python3 -m venv .venv这里有几个关键点:
python3 -m venv:这是调用venv模块的标准方式。.venv:这是虚拟环境目录的名称。使用以点开头的名称(如.venv,.env)是常见惯例,因为它通常是隐藏目录,不会干扰项目文件列表。你也可以用venv或env等任何名字。
步骤3:激活虚拟环境
source .venv/bin/activate激活后,你的命令行提示符通常会发生变化,前面会多出(.venv)字样,表示你已进入该虚拟环境。此时,你执行的python和pip命令都将指向虚拟环境内的版本,与系统全局环境隔离。
步骤4:在虚拟环境中工作
# 检查python和pip路径,确认已在虚拟环境中 which python # 应输出 /home/你的用户名/my_venv_project/.venv/bin/python which pip # 应输出 /home/你的用户名/my_venv_project/.venv/bin/pip # 安装包,例如安装requests pip install requests # 安装的包只会存在于当前虚拟环境的 .venv/lib/python3.x/site-packages/ 下 # 生成依赖列表(在项目根目录) pip freeze > requirements.txt步骤5:退出虚拟环境工作完成后,执行:
deactivate提示符前的(.venv)会消失,你回到了系统全局环境。
实操心得:我习惯将虚拟环境目录
.venv添加到项目的.gitignore文件中,避免将其提交到版本控制系统。因为虚拟环境是可以通过requirements.txt重建的,且可能包含与操作系统相关的二进制文件。
3.2 使用 virtualenv 搭建虚拟环境
步骤1:安装virtualenv首先确保有pip3,然后全局安装virtualenv:
pip3 install virtualenv步骤2:创建虚拟环境(指定Python版本)假设你需要一个基于Python 3.8的环境。首先,确保系统已安装Python 3.8:
sudo apt update sudo apt install python3.8 python3.8-venv -y然后创建环境:
cd ~ mkdir my_virtualenv_project && cd my_virtualenv_project # 创建环境,并使用 -p 指定解释器路径 virtualenv -p /usr/bin/python3.8 .venv这里-p参数是关键,它允许你指定任何已安装的Python解释器路径。你可以用which python3.8来查找准确路径。
步骤3:激活与使用激活和使用方式与venv完全一样:
source .venv/bin/activate # 此时python版本应为3.8 python --version # 安装包、生成requirements.txt等操作同上 pip install django==3.2 pip freeze > requirements.txt步骤4:退出环境
deactivate注意事项:
virtualenv创建的环境,其激活脚本(activate)位于bin目录下。在旧版Ubuntu或某些Shell配置下,可能需要使用source .venv/bin/activate而不是. .venv/bin/activate,前者兼容性更好。另外,如果你发现创建的环境无法激活或报错,检查一下是否在创建时使用了--system-site-packages参数(继承了系统包),有时这会导致路径冲突。
3.3 使用 pipenv 搭建虚拟环境
步骤1:安装pipenv同样通过pip3安装:
pip3 install pipenv步骤2:为项目创建虚拟环境并管理依赖pipenv的工作流是围绕项目目录进行的。
cd ~ mkdir my_pipenv_project && cd my_pipenv_project现在,假设你要安装flask作为生产依赖,pytest作为开发依赖。
# 安装生产依赖,这会自动创建虚拟环境(如果不存在)并更新Pipfile pipenv install flask # 安装开发依赖 pipenv install pytest --dev执行上述命令后,你会发现项目根目录下生成了两个文件:Pipfile和Pipfile.lock。
Pipfile:这是一个TOML格式的文件,清晰列出了项目依赖。[[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] flask = "*" [dev-packages] pytest = "*" [requires] python_version = "3.10"Pipfile.lock:这是一个JSON文件,锁定了所有依赖(包括次级依赖)的具体版本和哈希值,确保了环境的一致性。这个文件应该被提交到版本控制中。
步骤3:进入虚拟环境或直接在环境中运行命令有两种方式使用虚拟环境:
- 方式一:启动一个子Shell:
这会启动一个新的Shell会话,并自动激活虚拟环境。之后的操作就像在pipenv shellvenv激活的环境中一样。 - 方式二:不进入Shell,直接运行命令:
这种方式更干净,命令执行完毕后环境自动退出,不会改变当前Shell的状态。pipenv run python app.py pipenv run pytest
步骤4:管理依赖
- 更新所有依赖:
pipenv update - 更新指定包:
pipenv update flask - 卸载包:
pipenv uninstall flask - 查看依赖树:
pipenv graph,这个命令非常有用,可以清晰看到顶层依赖和次级依赖的关系。 - 从现有requirements.txt安装:
pipenv install -r requirements.txt
步骤5:退出环境如果你使用了pipenv shell进入了环境,退出只需输入:
exit踩坑实录:
pipenv默认将虚拟环境创建在全局位置(通常是~/.local/share/virtualenvs/下),而不是项目目录内。这可以通过设置环境变量PIPENV_VENV_IN_PROJECT=1来改变,让其创建在项目下的.venv目录中。我个人推荐设置这个变量,这样环境的位置更直观,也便于某些IDE(如VSCode)自动识别。在终端中执行export PIPENV_VENV_IN_PROJECT=1,或者将其写入你的Shell配置文件(如~/.bashrc)。
4. 进阶技巧、问题排查与维护心得
掌握了基本搭建方法后,一些进阶技巧和常见问题的处理能让你事半功倍。
4.1 虚拟环境的位置管理与清理
随着项目增多,虚拟环境会占用不少磁盘空间。定期清理无用的环境是个好习惯。
- 查找所有虚拟环境:
- 对于
venv/virtualenv创建在项目内的环境(如.venv),直接定位项目文件夹即可。 - 对于
pipenv默认创建在全局位置的环境,可以查看:ls ~/.local/share/virtualenvs/
- 对于
- 手动删除环境:最直接的方式就是删除整个虚拟环境目录。
# 确保已退出环境 (deactivate) rm -rf /path/to/your/project/.venv # 或删除pipenv的全局环境 rm -rf ~/.local/share/virtualenvs/Your-Project-Name-* - 使用
virtualenvwrapper(可选):这是一个管理virtualenv的扩展工具集,提供了workon、mkvirtualenv、rmvirtualenv等命令来集中管理所有环境。但它需要额外安装和配置,对于新手会增加复杂度,我个人在服务器上更倾向于直接管理目录。
4.2 依赖管理与迁移
如何将项目的依赖从一个环境复制到另一个环境或另一台机器?
venv/virtualenv+pip工作流:- 在源环境中激活环境,生成
requirements.txt:pip freeze > requirements.txt。 - 将
requirements.txt文件复制到新环境或新机器。 - 创建新的虚拟环境并激活。
- 安装依赖:
pip install -r requirements.txt。
- 在源环境中激活环境,生成
pipenv工作流:- 确保
Pipfile和Pipfile.lock都在项目目录中。 - 在新目录或新机器上,复制这两个文件。
- 运行
pipenv install(如果Pipfile.lock存在,它会优先根据锁文件安装精确版本;如果不存在,则根据Pipfile安装并生成锁文件)。 - 对于生产环境部署,为了绝对的一致性,应使用
pipenv install --ignore-pipfile,它只根据Pipfile.lock安装。
- 确保
4.3 常见问题与排查技巧
问题1:激活虚拟环境后,命令提示符没有变化,或者which python仍然指向系统路径。
- 排查:首先确认激活命令执行成功,没有报错。检查你使用的Shell。Ubuntu默认使用bash,激活脚本是
.venv/bin/activate。如果你使用的是zsh或fish,它们有自己对应的激活脚本(如activate.fish),但通常source .venv/bin/activate在bash和zsh下都有效。 - 解决:确保你是在当前Shell进程中执行
source命令,而不是在子Shell中执行。最稳妥的方式就是手动输入命令,而不是通过脚本间接调用。
问题2:在虚拟环境中安装包速度极慢,或者出现SSL证书错误。
- 排查:这通常是网络问题或PyPI镜像源的问题。
- 解决:为
pip配置国内镜像源。可以在激活虚拟环境后,使用以下命令临时安装或永久配置:
对于# 临时使用清华源安装单个包 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package # 永久配置(在虚拟环境中) pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simplepipenv,可以在Pipfile中修改[[source]]的url为国内镜像地址。
问题3:pipenv安装依赖时长时间卡在“Locking...”阶段。
- 排查:这是
pipenv在进行依赖解析,对于复杂依赖关系或网络不佳时可能很慢。 - 解决:
- 升级
pipenv:新版本通常有性能改进。pip install --upgrade pipenv。 - 使用更快的PyPI镜像:如上所述,修改
Pipfile的源。 - 跳过锁文件:对于临时测试,可以用
pipenv install --skip-lock,但这破坏了pipenv保证一致性的核心优势,不推荐用于生产。 - 考虑换用其他工具:如果性能问题持续困扰你,这正是很多人回归
pip+venv/virtualenv的原因之一。
- 升级
问题4:虚拟环境创建失败,提示“Error: Command '['.../python', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1.”
- 排查:这通常是因为系统Python安装不完整,缺少
ensurepip模块或相关组件。 - 解决:在Ubuntu上,安装完整的
python3-venv包。
对于sudo apt update sudo apt install python3-venvvirtualenv,也可以尝试安装python3-dev等包来确保编译环境完整。
4.4 与开发工具(VSCode)的集成
现代IDE能极大提升虚拟环境的使用体验。以VSCode为例:
- 打开项目文件夹。
- 按下
Ctrl+Shift+P(或Cmd+Shift+P),输入“Python: Select Interpreter”。 - 在弹出的列表中,VSCode会自动扫描项目目录下的虚拟环境(如
.venv、env等)以及系统环境。选择你刚刚创建的虚拟环境中的python解释器(例如,./.venv/bin/python)。 - 选择后,VSCode底部的状态栏会显示当前使用的Python解释器。之后你在VSCode终端里启动的Python、运行的调试配置,都会自动使用这个虚拟环境。
这个集成对于pipenv创建的环境同样有效,只要你能在文件系统中找到那个python可执行文件(无论是在项目内的.venv还是全局的virtualenvs目录下)。
5. 总结与个人工作流建议
经过对venv、virtualenv和pipenv的详细拆解,我们可以看到,没有绝对的“最好”,只有“最适合”。它们分别代表了不同层次的需求:内置轻量、灵活强大、一体现代。
我个人的工作流是这样的,供你参考:
对于服务器部署、一次性脚本或教学演示,我首选venv。因为它无需额外安装,命令简单,足够完成隔离环境的基本任务。在Docker容器内构建应用时,也经常用venv来保持镜像层的最小化。
对于需要兼容特定Python版本(尤其是老版本)的项目,或者我个人主要的本地开发项目,我使用virtualenv。它的-p参数无可替代,而且pip freeze > requirements.txt的流程我已经肌肉记忆了,非常可靠。配合一个清晰的requirements.txt文件,项目结构一目了然。
对于全新的、我打算认真维护且可能与他人协作的Python应用项目,我会给pipenv一个机会。特别是它的Pipfile.lock机制,在团队协作和CI/CD流水线中,能严格保证开发、测试、生产环境的一致性,这一点非常有吸引力。我会设置PIPENV_VENV_IN_PROJECT=1,并把Pipfile和Pipfile.lock都纳入版本控制。
最后,无论选择哪种工具,养成使用虚拟环境的习惯是提升Python开发体验、避免环境混乱的最重要一步。在Ubuntu上,这更是对系统稳定性的负责。刚开始你可能会觉得多了一步“激活环境”很麻烦,但当你同时处理多个项目而不再为依赖冲突焦头烂额时,你会感谢这个好习惯的。