Featured image of post Uv:一个用Rust编写的极速Python包和项目管理工具

Uv:一个用Rust编写的极速Python包和项目管理工具

python项目结构发展

go与rust的项目结构都简洁得仿佛自带强迫症,而python恰恰相反,它在诞生之初根本没有考虑过工程项目这回事。所以早期的python项目十分放飞自我,好在官方一直持续打补丁,和一些早期python好的项目结构十分相似。

一个现代的python项目应该如何组织?

现在python的项目管理基本被分成了两大流派:

  1. conda:由Anaconda公司提供的一个商业软件,pixi也属于conda宇宙

    有自己的配置文件,软件仓库,就连python解释器都是它自己编译的

  2. 官方python体系

虚拟环境

当我们需要运行一个flask项目下的 main.py 文件,首先想到的就是:

pip install flask

pip工具会自动帮你安装最新版的flask 3.1.1,但这么做系统默认是安装到了全局的python环境,这样会带来两个问题:

  1. 版本冲突
  2. 依赖地域

——虚拟环境venv就是为了解决这两个问题而设计出来的,它会为每一个python项目提供一个干净独立的python环境

python -m venv .venv

这会在项目的目录下创建一个.venv的目录,这时候重新进行 pip install flask ,依赖包会安装到.venv/lib目录下

虚拟环境的底层原理

虚拟环境的底层逻辑十分简单,其实就是修改了sys.path这个变量,sys.path本身是一个列表,里面记录了python在导入模块时需要搜索的一系列文件夹路径。当我们执行 from flask import Flask 的时候,python就会严格地检查这些路径。

当虚拟环境被激活的时候,sys.path中会被添加.venv这个路径;反之,在虚拟环境没有被激活的时候,使用的就是全局路径

环境复现的问题

当我们创建了一个python项目,如何准确地将环境分享给其他人?(总不能一行行pip install吧)

最早的做法

是使用 pip freeze > requirements.txt 这个命令,会将当前环境下所有的依赖包打印到requirements.txt这个文件下。别人只需要在自己的虚拟环境下执行 pip install -r requirements.txt 即可安装所有的依赖

但这么做有一个缺陷,pip分不清什么是项目需要的直接依赖,什么是直接依赖引入的间接依赖

当项目体量不大时,这么做没什么问题,但一旦项目依赖变多,情况就要失控了。

pyproject.toml

现在官方推荐的做法是通过pyproject.toml这一个配置文件来进行项目管理

我们只需要在dependencies中添加直接依赖,再执行 pip install -e. 即可安装项目依赖

uv

总结一下,我们通过venv解决了环境依赖问题,用pyproject.toml管理环境中的依赖

但这套纯手工的流程属实有点麻烦,因为我们不能像以前一样通过一条pip命令直接安装依赖了

而是需要去pip软件仓库查询对应的软件包和版本号,并且添加到配置文件中

那么python有没有提供一个软件包来解决这个问题呢?——很遗憾,并没有

但有uv这样的第三方工具,可以把它理解为对venv和pip的高级封装,它在底层还是使用的pip和venv

通过uv进行项目管理

回顾一下之前管理项目的步骤

  1. python -m venv .venv
  2. source .venv/bin/activate
  3. edit pyproject.toml
  4. 在dependencies中添加flask ≥ 3.1.1
  5. pip install -e .

现在有个uv,我们只需要执行 uv add flask 这一条命令,就能完成所有的事情:

  • 自动修改pyproject.toml,将flask添加到dependencies中
  • 检查并自动创建.venv的虚拟环境
  • 把这个包和所有的间接依赖安装到虚拟环境中

如果我是项目的协作者,从别人手里拿到这个项目,只需要执行 uv sync ,即可自动搭建好虚拟环境并安装好项目所需所有的依赖

通过uv管理项目同时也能兼容传统的方法 python main.py,也能直接通过一条 uv run main.py

它会在虚拟环境的上下文中执行命令,我们不需要手动激活环境,uv会自动找到环境并在其中启动项目。

uv的核心目的就是把我们从繁琐的环境和依赖中解放出来

Licensed under CC BY-NC-SA 4.0