- 由 虚拟的现实创建于4月 07, 2025 需要 4 分钟阅读时间
简介
Python 包管理生态中存在多种工具,如 pip、pip-tools、poetry、conda 等,各自具备一定功能。与其他Python中的包管理工具相比,uv更像是一个全能选手,它的优势在于:
- 速度快:得益于 Rust,uv工具的速度让人惊艳,比如安装依赖,速度比其他工具快很多
- 功能全面:uv 是“一站式服务”的工具,从安装 Python、管理虚拟环境,到安装和管理包,再到管理项目依赖,它统统都能处理得很好
- 前景光明:背后有风投公司 Astral 支持,且采用了 MIT 许可,即使未来出现问题,社区也有应对的办法
使用 uv,也可以像 NodeJS 或者 Rust 项目那样方便的管理依赖。
安装
安装 uv 非常简单,可以使用官方提供的安装脚本,也可以通过pip来安装。
# On macOS and Linux. curl -LsSf https://astral.sh/uv/install.sh | sh # On Windows. powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" # With pip. pip install uv
安装之后,可以通过 uv help 命令检查是否安装成功:
使用
首先,介绍 uv 工具主要使用的两个文件:
- pyproject.toml:定义项目的主要依赖,包括项目名称、版本、描述、支持的 Python 版本等信息
- uv.lock:记录项目的所有依赖,包括依赖的依赖,且跨平台,确保在不同环境下安装的一致性。这个文件由 uv 自动管理,不要手动编辑
创建项目
接下来,创建一个项目,使用 uv init <project dir>命令。
$ uv init myproject Initialized project `myproject` at `D:\projects\python\myproject` $ cd .\myproject\ $ ls 目录: D:\projects\python\myproject Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2024/12/27 12:06:08 109 .gitignore -a---- 2024/12/27 12:06:08 5 .python-version -a---- 2024/12/27 12:06:08 87 hello.py -a---- 2024/12/27 12:06:08 155 pyproject.toml -a---- 2024/12/27 12:06:08 0 README.md
通过init创建项目之后,uv工具贴心地帮助我们生成了一些默认文件。
其中 hello.py 只是一段演示用的代码,随后我们可以根据实际的项目需要删除这个代码文件,换成自己的实际代码。
$ cat .\hello.py def main(): print("Hello from myproject!") if __name__ == "__main__": main()
pyproject.toml中是一些项目信息:
$ cat .\pyproject.toml [project] name = "myproject" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = []
注意,uv init 创建项目之后,会自动将项目使用 Git 来管理。
操作环境
创建项目之后,我们进入项目根文件夹的第一件事就是同步项目依赖。
$ uv sync Using CPython 3.12.4 interpreter at: D:\miniconda3\envs\databook\python.exe Creating virtual environment at: .venv Resolved 1 package in 15ms Audited in 0.05ms
同步之后,会自动查找或下载合适的 Python 版本,创建并设置项目的虚拟环境,构建完整的依赖列表并写入 uv.lock 文件,最后将依赖同步到虚拟环境中。
$ ls 目录: D:\projects\python\myproject Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2024/12/27 12:12:39 .venv -a---- 2024/12/27 12:06:08 109 .gitignore -a---- 2024/12/27 12:06:08 5 .python-version -a---- 2024/12/27 12:06:08 87 hello.py -a---- 2024/12/27 12:06:08 155 pyproject.toml -a---- 2024/12/27 12:06:08 0 README.md -a---- 2024/12/27 12:12:39 116 uv.lock $ cat .\uv.lock version = 1 requires-python = ">=3.12" [[package]] name = "myproject" version = "0.1.0" source = { virtual = "." }
uv sync 同步之后,就可以运行项目的代码了。
既然使用 uv 管理项目的话就使用 uv 的命令来运行代码,不要像以前那样使用python xxx.py来运行。以试着运行项目创建时自动生成的代码。
$ uv run .\hello.py Hello from myproject!
管理依赖
管理依赖是我使用uv工具的主要目的,使用uv添加依赖非常简单,和npm和cargo差不多。
$ uv add pandas Resolved 7 packages in 3.41s Prepared 6 packages in 4.63s Installed 6 packages in 1.80s + numpy==2.2.1 + pandas==2.2.3 + python-dateutil==2.9.0.post0 + pytz==2024.2 + six==1.17.0 + tzdata==2024.2
尝试安装了一个pandas依赖(pandas依赖的包也自动安装了),从上面日志可以看出速度非常快。这时再看看uv.lock 文件的变化。
$ cat .\uv.lock version = 1 requires-python = ">=3.12" [[package]] name = "myproject" version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "pandas" }, ] [package.metadata] requires-dist = [{ name = "pandas", specifier = ">=2.2.3" }] [[package]] name = "pandas" version = "2.2.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "python-dateutil" }, { name = "pytz" }, { name = "tzdata" }, ] [[package]] name = "pytz" version = "2024.2" source = { registry = "https://pypi.org/simple" }
上面的日志中我删除了很多内容,因为整体内容太多,详细记录了每个包以及它依赖的包的情况。
uv.lock 这个文件我们不要手动去编辑它,使用 uv 工具去管理它。引入了 pandas 之后,看看是否可以在 hello.py 中使用。
$ cat .\hello.py import pandas as pd def main(): print("Hello from myproject!") df = pd.DataFrame( { "A": [1, 2, 3], "B": [4, 5, 6], } ) print(df) if __name__ == "__main__": main() $ uv run .\hello.py Hello from myproject! A B 0 1 4 1 2 5 2 3 6
可以正常使用安装的包pandas,下面在试试删除依赖会怎么样。
$ uv remove pandas Resolved 1 package in 12ms Uninstalled 6 packages in 1.18s - numpy==2.2.1 - pandas==2.2.3 - python-dateutil==2.9.0.post0 - pytz==2024.2 - six==1.17.0 - tzdata==2024.2 $ cat .\uv.lock version = 1 requires-python = ">=3.12" [[package]] name = "myproject" version = "0.1.0" source = { virtual = "." }
使用uv remove命令删除pandas包之后,也会自动删除pandas依赖的其他包,
我们看到uv.lock 文件也恢复到最初的内容。再试试运行hello.py看看。
$ uv run .\hello.py Traceback (most recent call last): File "D:\projects\python\myproject\hello.py", line 1, in <module> import pandas as pd ModuleNotFoundError: No module named 'pandas'
果然,无法运行了。
区分开发和生产环境
还有一个比较常用的功能是区分开发环境和生产环境的依赖,这个功能在NodeJS和Rust中很常见。
比如,我们想把pandas安装到开发环境中,而把requests安装到生产环境中。
$ uv add --group dev pandas Resolved 7 packages in 1.72s Installed 6 packages in 1.39s + numpy==2.2.1 + pandas==2.2.3 + python-dateutil==2.9.0.post0 + pytz==2024.2 + six==1.17.0 + tzdata==2024.2 $ uv add --group production requests Resolved 12 packages in 2.72s Prepared 5 packages in 1.31s Installed 5 packages in 68ms + certifi==2024.12.14 + charset-normalizer==3.4.1 + idna==3.10 + requests==2.32.3 + urllib3==2.3.0
安装之后,uv.lock 文件自动添加了各个包及其依赖,这里不再赘述。
从项目的pyproject.toml中可以看出不同环境的包依赖。
$ cat .\pyproject.toml [project] name = "myproject" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [] [dependency-groups] dev = [ "pandas>=2.2.3", ] production = [ "requests>=2.32.3", ]
- 无标签