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

Python 包与环境管理简史:从混乱到优雅

自动包管理工具的先驱:easy_install

在一切规范化工具出现之前,Python 的包管理是相当原始的。开发者们需要把第三方库的源码下载下来,手动放到项目目录里。
为了解决自动安装包的问题,easy_install 应运而生。

2004年:easy_install——从 0 到 1 的突破

easy_install 是 Python 包管理的早期自动化解决方案。它可以从 PyPI 自动下载并安装包,极大地简化了获取第三方库的流程。然而,它也存在很多问题:

  • 无法直接卸载:安装容易,卸载却需要手动删除文件。
  • 无依赖管理:它会安装包及其所有依赖,但无法记录或锁定这些依赖的精确版本,导致“依赖地狱”问题依然存在。
  • 容易冲突:多个项目依赖同一个库的不同版本时,easy_install 会陷入困境。

虚拟环境管理+更智能的包管理:virtualenv/venv,pip

2008年:virtualenv——为每个项目建一个虚拟环境

virtualenv 的出现是一个里程碑。它创造性地提出可以为每个项目创建一个独立的、隔离的 Python 虚拟环境。在这个虚拟环境里,你可以随心所欲地安装任何版本的包,而不会影响到系统全局或其他项目。virtualenv 解决了项目间的环境冲突问题,为后续的工具发展奠定了基础。

2011年:pip——更智能的包安装器

pip 作为 easy_install 的替代品逐渐成熟,并最终成为 Python 事实上的标准包安装器。它解决了 easy_install 的诸多痛点:

  • 可以一条命令卸载包
    pip uninstall package_name
    
  • 支持依赖管理:能够自动处理依赖关系。
  • 引入 requirements.txt:通过一个简单的文本文件,你可以记录项目所需的所有依赖及其精确版本。其他人拿到项目后,只需运行
    pip install -r requirements.txt
    
    就能复刻你的开发环境。

2012年:venv——Python内置的虚拟环境工具

venv 是 Python 3.3 引入的一个标准库模块,它提供了 virtualenv 的核心功能,但更加轻量和易用。你可以通过

python -m venv my_env

来创建一个新的虚拟环境,而无需额外安装任何东西。

早期版本的venv相比virtualenv,缺少很多高级特性,因此很多开发人员仍然选择继续使用virtualenv。但随着Python的发展,venv也越来越成熟,目前已经取代了virtualenv成为了虚拟环境的事实性官方标准。

Python解释器版本管理工具:pyenv

pipvirtualenv/venv 解决了“包”和“环境”的问题,但还有一个更底层的问题:Python 解释器本身呢?如果你的电脑系统自带了 Python 2.7,但你的新项目需要 Python 3.10,而另一个维护中的老项目又需要 Python 3.3,怎么办?手动安装、修改 PATH?太麻烦了。

2011年:pyenv——掌控你的 Python 版本

pyenv 的出现,完美地填补了这个空白。它深受 Ruby 社区的 rbenv 启发,其核心思想非常巧妙:它并不真正地“安装”多个 Python 版本,而是在你的 PATH 路径最前面插入一个“垫片”(shim)。当你调用 python 命令时,这个垫片会根据你当前目录或全局的配置,智能地转发给对应版本的 Python 解释器。

通过

pyenv install 3.10.0

命令,你可以轻松安装任意版本的Python(此处示例3.10.0)

通过

pyenv local 3.8.5

命令,你可以为当前目录下的项目指定使用任意版本的Python(此处示例3.8.5)

pyenv 解决了 Python 解释器版本管理的难题,它与 pipvenv 形成了三件套:pyenv 负责管理解释器版本,venv 负责创建隔离环境,pip 负责安装依赖包

一体化工具的尝试:pipenvpoetry

pyenv + virtualenv + pip 虽然强大,但毕竟需要操作三个工具。开发者们开始向往一个能“一键搞定所有”的解决方案。于是,一系列“All-in-One”工具应运而生。

2017年:Pipenv——官方推荐的“希望”

Pipenv 由 Requests 库的作者 Kenneth Reitz 主导开发,并一度被 Python 官方推荐为“用于 Python 项目的官方依赖管理工具”。它试图将 pipvenv 的功能合二为一。

它用 Pipfile和 Pipfile.lock替代了 requirements.txt,提供了更精确的依赖锁定和开发/生产环境的区分。

同时,Pipenv 在早期因为一些性能问题、锁文件生成缓慢以及偶尔的 Bug,社区评价褒贬不一,逐渐失去了一些光环。

Pipenv 本身不管理 Python 解释器版本。所以pyenv在管理不同Python版本的多个项目时仍是必需的工具。(笔者并没有真正使用过pipenv这个工具,根据网上的资料查询得出这个结论,不太确定是不是真的没有这个功能。如果有误,请不吝赐教)

2018年:Poetry——更现代的依赖管理工具

几乎与 Pipenv 同期,Poetry 横空出世,并迅速赢得了大量开发者的心。

它使用 pyproject.toml作为唯一的配置文件,这是 PEP 518 和 PEP 621 所倡导的现代 Python 项目标准,非常简洁和强大。

它的依赖解析算法和锁文件(poetry.lock)生成速度比 Pipenv 更快、更可靠。

另外,它集成了构建、打包和发布到 PyPI 的功能,真正实现了从开发到部署的全流程管理。

pipenv一样,Poetry自身不负责Python版本的管理,仍然需要搭配pyenv来管理Python解释器版本。(笔者并没有真正使用过poetry这个工具,根据网上的资料查询得出这个结论,不太确定是不是真的没有这个功能。如果有误,请不吝赐教)

另一条路:科学计算领域的王者——Conda

在主流 Python 社区为 pipvirtualenv 演进时,科学计算领域走出了另一条完全不同的道路。

2012年:Conda——安装依赖、Python版本管理全包了

Anaconda是数据科学领域发展出的包管理+Python版本管理工具。而且它管理的不仅仅是 Python 包,还可以是R语言等其他语言的软件包。此外,为了提供开箱即用的机制,Anaconda会默认安装许多常用的科学计算库,但这也导致了安装体积过大。因此,又推出了miniconda这个精简版,它只包含了最基本的 Python 和 conda 包管理器。对于Python开发人员来说,更多使用的还是miniconda

Anaconda 在安装时就会自带一个稳定版本的Python,同时还可以通过conda命令直接安装其他版本的Python。

conda create -n myenv python=3.9

这条命令,就可以创建一个包含 Python 3.9 的新环境。

Anaconda可以不依赖pip,直接通过conda install命令安装包。但是conda安装的包版本常常会和pip包冲突,而且PyPI上的很多包都没有conda的版本。

另外,Anaconda使用environment.yml文件来描述环境,这个文件类似于requirements.txt,但更加复杂。在conda中,通过yaml文件来创建环境的命令为:

conda env create -f environment.yml -n 环境名

但说实话能够一次性成功配置环境属于少数情况,一般都会遇到配置太慢、卡死、solving environment failed、PackageNotFound、以及pip爆出的一堆红字。

综合上述原因,在实际的工作流中,人们通常会使用conda创建一个干净的虚拟环境,然后再在这个虚拟环境中使用pip安装其他依赖。

conda create -n myenv python=3.9
conda activate myenv
pip install -r requirements.txt

这也是现在科研领域使用Python的主要方式,绝大多数的Python科研项目都是这样安装依赖的。另外一些老的软件开发项目也会使用这种方式。VSCode对于conda的兼容性也很好,可以直接检测出conda管理的虚拟环境。

速度与整合的终极追求:uv 的时代

时间来到最近,一个名为 uv 的工具横空出世,以其惊人的速度和“大一统”的雄心,再次搅动了整个生态。

2023年:uv ——极速的全面解决方案

uv 由 Astral(Ruff 的开发公司)发布,它是一个用 Rust 编写的、极其快速的 Python 包安装器,最初旨在成为 pip 的直接替代品。
使用

uv pip install package_name

命令,可以极大地提升安装速度。它的速度优势是颠覆性的,将依赖解析和安装的时间从分钟级缩短到了秒级。

uv 的目标远不止于作为一个快速的pip替代品,它正在迅速整合 Python 项目管理的所有核心能力:

  • 项目管理uv init可以快速创建一个包含 pyproject.toml 的项目骨架。
  • 虚拟环境管理uv venv 可以创建和管理虚拟环境。
  • 依赖解析与安装uv adduv removeuv sync 等命令提供了原生的依赖安装体验
  • Python 版本管理:可以通过uv python install命令安装指定的Python版本

现在仅使用uv一个工具就可以实现原本需要pip,venv,pyenv三个工具才能实现的功能。而且相比conda,其更符合Python标准,更加Pythonic。

笔者个人使用经历和体会

前面这段是对历史的梳理,现在来谈一谈我个人使用Python依赖管理工具的经历和体会。

本科毕业后,我先从事了两年NodeJS开发的工作。我个人感觉相对来说NodeJS的版本兼容性应该比Python好不少吧?当时压根就没想到需要不同的NodeJS版本来管理不同项目的问题,用我电脑上安装的NodeJS LTS(长期支持版)运行公司的各个项目都没有遇到兼容性问题。另外,NodeJS中使用npm工具管理项目依赖包,每个项目就是一个独立的环境,也不会出现不同项目之前依赖包冲突的问题。虽然现在也出现了nvm这个管理不同Nodejs版本的工具,但这个工具只是锦上添花,在大多数情况下并不是必需的。

但读研以后开始使用Python,整个情况就变了。不同版本的Python之间兼容性很差,只安装一个Python版本完全无法应对不同的项目,而且pip安装依赖在没有虚拟环境的情况下,默认是到全局环境,无法进行不同项目的环境隔离。

conda是我最早接触的工具,因为我是读研后才开始使用Python的,一开始主要做的也是科研项目。实验室的师兄师姐教我们就是直接用conda,而且基本上所有的科研论文项目的主页上也都是用的conda。venv作为Python官方的虚拟环境解决方案我也了解过,但还是不如conda方便,基本没用过。有了conda以后,项目的版本依赖管理就变得清晰了很多,而且在conda里面想用哪个版本的Python就可以用哪个版本的Python。

conda自带的conda install命令在很多时候安装不到想要的包,而且速度很慢。所以我都是先用conda安装虚拟环境,再用pip安装依赖。

假如我想导出环境给另一台电脑使用该怎么办呢?一开始使用的是这个命令:

pip freeze > requirements.txt

但是这样会存在一个问题,导出的文件包含的是当前虚拟环境中所有的包。有的时候为了图省事,一个conda虚拟环境会给多个项目使用,这样就可能包含很多用不着的包。为了解决这个问题,我又找到了pipreqs这个工具,该工具会扫描当前项目下实际使用的依赖包,并生成对应的requirements.txt文件。

尽管pipreqs工具可以导出实际需要的依赖,但仍然需要手动导出。但使用过npm的我还是觉得不太方便,为什么就不能在安装的同时直接生成一个类似于package.json的文件来管理依赖呢?(其实pyproject.toml文件早已出现,但由于读研期间把绝大多数的精力都放在读论文,想科研点子上,没有时间学习开发工具的使用,一直活在自己的信息茧房里,也就不知道这个东西的存在)

一直到了研究生毕业,再次工作以后,我接触了Dify项目,发现其中使用了一种新的依赖管理工具uv,而且使用pyproject.toml管理项目依赖包。这不就是我梦寐以求的工具吗?再去回看历史,发现原来之前还有poetry,pipenv这些工具。而uv基本上解决了之前所有工具的问题。现在的Python开发人员真是身处一个好时代,有uv这么好的工具。

最后说一下工具的选型。

对于科研人员来说,还是推荐使用conda。尽管其比较笨重,但使用方便,而且也是科研领域的主流解决方案。

但对于开发人员来说,强烈建议转向uv这个现代化工具。这是目前Python依赖管理的集大成者。

http://www.wxhsa.cn/company.asp?id=7749

相关文章:

  • qoj853 Flat Organization
  • shell命令中循环执行操作的命令
  • 2025年9月中国数据库排行榜:达梦挺进榜眼位,崖山首入前十强
  • 基于QEMU模拟器搭建Builtroot下的QT开发环境
  • vlan
  • windosw 配置arp绑定
  • 2024年最受欢迎的渗透测试工具盘点
  • Unity学习 5.6 FBX
  • SEERC 2022 题面简要翻译
  • 【稳定检索、线上线下参会、马理工主办】第十一届建筑、土木与水利工程国际学术会议(ICACHE 2025)
  • telnet安装与开启
  • 20250917NOIP#21
  • 又一个新项目完结,炸裂!
  • 阿里云防刷神器ESA搞活动免费领取
  • 报错TypeError: Unknown file extension .ts - broky
  • 抗 IgE 单克隆抗体联合变应原免疫治疗(AIT):过敏性疾病治疗的协同新策略
  • php怎么关闭数据库连接
  • 代码分析之污点分析 - 教程
  • 设计模式 7章
  • 磁盘存储简介-轮子
  • 洛谷 P1967 [NOIP 2013 提高组] 货车运输 题解
  • cherry-pick 合并曾今某一次提交
  • 向量数据库 FAISS、LanceDB 和 Milvus
  • ruoyi-vue自动生成代码
  • 拥抱新一代 Web 3D 引擎,Three.js 项目快速升级 Galacean 指南
  • Fast IO 模板
  • kylin V11安装mysql8.4.5(glibc.2.28版本)
  • iOS 上架 App 流程全解析 苹果应用发布步骤、App Store 审核流程、ipa 文件上传与 uni-app 打包实战经验
  • P6801 花式围栏
  • ms sql dml 操作