这篇文章深入介绍 uv 管理 Python 项目的使用

Features

Python versions

Scripts

Projects

使用 pyproject.toml 配置项目

Tools

允许与安装工具

The pip interface

手动管理环境与包, 用于旧的工作流, 或一些高级命令功能

下面命令手动管理环境中的包 (替代 pippipdeptree)

在环境中锁定包 (替代 pip-tools)

Utility

管理与检查 uv 的状态, 例如缓存、存储目录或子升级

Projects

Structure and files

Python 项目依赖元数据定义在 pyproject.toml 中, uv 依赖这个文件来确定项目根目录.

一个最小的项目定义包含名称和版本

TOML
[project]
name = "example"
version = "0.1.0"
Click to expand and view more

额外的项目元数据和配置包含:

The project environment

使用 uv 处理项目时, uv 会根据需要创建虚拟环境. 虽然某些 uv 命令会创建临时环境 (uv run --isolated), 但 uv 也会在 pyproject.toml 旁边的 .venv 目录中管理一个持久环境, 其中包含项目及其依赖项. 它存储在项目内部是为了方便编辑器查找, 编辑器需要环境来提供代码补全和类型提示. 不建议将 .venv 目录包含在版本控制中, 它会通过内部 .gitignore 文件自动从 git 中排除.

要在项目环境中运行命令, 应该使用 uv run. 或者, 项目环境可以像普通虚拟环境一样正常激活.

当调用 uv run 时, 如果项目环境尚不存在, 它将创建项目环境, 如果已存在则确保其是最新的. 项目环境也可以通过 uv sync 显式创建.

不建议手动修改项目环境, 例如使用 uv pip install. 对于项目依赖项, 使用 uv add 将包添加到环境中. 对于一次性需求, 使用 uvxuv run --with.

TIP 提示

如果不希望 uv 管理项目环境, 设置 managed = false 来禁用项目的自动锁定和同步, 例如:

TOML
[tool.uv]
managed = false
Click to expand and view more

The lockfile

uv 会在 pyproject.toml 旁边创建一个 uv.lock 文件.

uv.lock 是一个通用或跨平台锁文件, 它捕获在所有可能的 Python 标记 (操作系统、架构和Py版本) 上将要安装的包.

与用于指定项目广泛要求的 pyproject.toml 不同, 锁文件包含在项目环境中安装的确切解析版本. 此文件应检入版本控制, 以允许在不同机器上进行一致且可重现的安装.

锁文件确保从事项目工作的开发人员使用一致的包版本. 它确保在将项目部署为应用程序时,已知使用的确切包版本.

锁文件在使用项目环境的 uv 调用期间自动创建和更新, 即 uv syncuv run. 锁文件也可以使用 uv lock 显式更新.

uv.lock 是一个人类可读的 TOML 文件, 但由 uv 管理, 不应手动编辑. uv.lock 格式专用于 uv, 其他工具无法使用.

Relationship to pylock.toml

在 PEP 751 中, Python 标准化了一种新的解析文件格式 pylock.toml. pylock.toml 是一种解析输出格式,旨在替代 requirements.txt. pylock.toml 是标准化的且与工具无关的, 这样在未来, uv 生成的 pylock.toml 文件可以由其他工具安装. uv 的某些功能无法在 pylock.toml 格式中表达; 因此, uv 将继续在项目接口中使用 uv.lock 格式.

但是, uv 支持将 pylock.toml 作为导出目标以及在 uv pip CLI 中使用:

Creating projects

uv 支持使用 uv init 创建项目. 当创建项目时, uv 支持两种基本的模板: applicationslibraries. 默认 uv 会创建应用项目, 使用 --lib flag 可以创建 library 项目.

Target directory

uv 会在工作目录创建项目, 或者在目标目录, 例如 uv init foo. 如果这个位置已经存在项目了, uv 会退出并报错.

Applications

应用项目模板很适合 web 服务器、脚本和命令行接口. 该模板是默认的 uv init 生成目标, 也可以使用 --app flag 显示指定

BASH
uv init example-app
Click to expand and view more

项目结构包含一个 pyproject.toml、一个样本文件 main.py 一个 readme 和一个 Python 版本文件 .python-version

pyproject.toml 文件包含了基本的元数据. 不包含构建系统, 它不是一个包, 并且不会在环境中安装.

TOML
[project]
name = "example-app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
Click to expand and view more

main.py 文件有类似下面的样板

PYTHON
def main():
    print("Hello from example-app!")

if __name__ == "__main__":
    main()
Click to expand and view more

通过下面命令运行 python 代码

BASH
uv run main.py
Click to expand and view more

Packaged applications

如果是想要创建一个命令行工具, 并发布到 PyPI 上面, 可以使用 package 模板.

BASH
uv init --package example-pkg
Click to expand and view more

main.py 被替换为 src/ 目录, 该目录中会包含一个模块目录, 以及一个 __init__.py 文件.

Build system 被定义了, 因此该项目会被安装到环境中, pyproject.toml 类似下面这样:

TOML
[project]
name = "example-pkg"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []

[project.scripts]
example-pkg = "example_pkg:main"

[build-system]
requires = ["uv_build>=0.8.20,<0.9.0"]
build-backend = "uv_build"
Click to expand and view more

命令也被定义了, 可以使用下面这样命令运行 uv run

BASH
uv run exmaple-pkg
Click to expand and view more

Libraries

一个库提供函数和对象为其他项目使用. 库需要构建和分发, 例如上传到 PyPI. 使用 --lib flag 来创建库结构.

BASH
uv init --lib example-lib
Click to expand and view more

类似 packaged application, 项目采用了 src/ 布局, 其中包含一个 py.typed 标记文件, 用于告知使用者此库提供了类型注解信息.

TOML
[project]
name = "example-lib"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []

[build-system]
requires = ["uv_build>=0.8.20,<0.9.0"]
build-backend = "uv_build"
Click to expand and view more

可以自行选择不同的构建后端, 使用 --build-backend 结合 hatchling, uv_build, flitcore, pdm-backend, setuptools, maturinscikit-build-core 等使用.

创建的模块定义了一个简单的 API 函数 __init__.py

PYTHON
def hello() -> str:
    return "Hello from example-lib!"
Click to expand and view more

然后可以使用 uv run 运行

BASH
uv run python -c "import example_lib; print(example_lib.hello())"
Click to expand and view more

Projects with extension modules

大多数 Python 项目都是 “pure Python”, 这意味着他们不使用其他语言定义模块, 例如 C, C++, FORTRAN 或 Rust. 然而, 使用扩展模块的项目通常在性能敏感的代码中使用.

创建一个扩展模块需要选择一个构建系统. uv 支持下面的构建系统:

使用 --build-backend flag 指定构建系统

PLAINTEXT
uv init --build-backend maturin example-ext
Click to expand and view more

这个项目包含一个 Cargo.toml 和一个 src/lib.rs 文件.

Rust 库定义了一个简单的函数

RUST
use pyo3::prelude::*;

#[pyfunction]
fn hello_from_bin() -> String {
    "Hello from example-ext!".to_string()
}

#[pymodule]
fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(hello_from_bin, m)?)?;
    Ok(())
}
Click to expand and view more

并在 Python 模块中将其导入, src/example-ext/__init__.py 内容如下:

PYTHON
from example_ext._core import hello_from_bin

def main() -> None:
    print(hello_from_bin())
Click to expand and view more

可以使用下面命令执行

BASH
uv run example-ext
Click to expand and view more

Creating a minimal project

如果只想创建一个 pyproject.toml 使用 --bare 选项

BASH
uv init example --bare
Click to expand and view more

Managing dependencies

Dependency fields

项目依赖由以下几个字段定义

NOTE

项目的 project.dependenciesproject.optional-dependencies 字段即使不发布也能使用.

uv 支持使用 uv adduv remove 来定义项目依赖, 但也可以直接修改 pyproject.toml.

Adding dependencies

例如这样

BASH
uv add httpx
Click to expand and view more

可以添加一个项目依赖

TOML
[project]
name = "example"
version = "0.1.0"
dependencies = ["httpx>=0.27.2"]
Click to expand and view more

使用 --dev, --group, --optional flag 可以用来为可选字段添加依赖. 依赖将会添加一个约束, 例如 >=0.27.2, 这是最近的兼容版本. 这样的约束可以使用 --bounds 调整, 或者直接提供约束.

TOMO
uv add "httpx>=0.20"
Click to expand and view more

当从源添加一个依赖而不是 package registry 的时候, uv 会在源字段中添加一个条目, 例如下面从 GitHub 添加 httpx:

PLAINTEXT
uv add "httpx @ git+https://github.com/encode/httpx"
Click to expand and view more

这会在 pyproject.toml 添加一个 Git 入口源:

TOML
[project]
name = "example"
version = "0.1.0"
dependencies = [
    "httpx",
]

[tool.uv.sources]
httpx = { git = "https://github.com/encode/httpx" }
Click to expand and view more

如果依赖无法添加, uv 将会输出一个报错.

可以使用 -r 选项添加 requirements.txt 里面的依赖

BASH
uv add -r requirements.txt
Click to expand and view more

Removing dependencies

使用下面命令移除依赖

BASH
uv remove httpx
Click to expand and view more

使用 --dev, --group--optional flags 来移除其他特定的依赖. 如果被移除的依赖项定义了源, 并且没有其他依赖项引用它, 那么这个源也将被一并移除.

Changing dependencies

如果要修改现有的依赖, 可以这样

BASH
uv add "httpx>0.1.0"
Click to expand and view more

使用一个不同的依赖源

BASH
uv add "httpx @ .../httpx"
Click to expand and view more

Platform-specific dependencies

为了使用只在具体平台的依赖或具体的 Python 版本, 使用 environment markers.

例如, 只在 Linux 平台安装 jax:

BASH
uv add "jax; sys_paltform == 'linux'"
Click to expand and view more

这会使 pyproject.toml 包含下面这样的定义

TOML
[project]
name = "project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["jax; sys_platform == 'linux'"]
Click to expand and view more

相似的, 只为 Python 3.11 之后的版本添加 numpy:

BASH
uv add "numpy; python_version >= '3.11'"
Click to expand and view more

Project dependencies

project.dependencies 代表上传到 PyPI 或者构建 wheel 使用的依赖. 单独依赖具体使用 dependency specifiers 语法, 并遵循 PEP 621 标准.

project.dependencies 定义了一个项目需要的依赖列表, 以及需要的版本限制. 每一项都包含一个项目名称和项目版本号, 有些项还包含额外的 environment markers, 例如:

TOML
[project]
name = "albatross"
version = "0.1.0"
dependencies = [
    # Any version in this range
    "tqdm >=4.66.2,<5",
    # Exactly this version of torch
    "torch ==2.2.2",
    # Install transformers with the torch extra
    "transformers[torch] >=4.39.3,<5",
    # Only install this package on older python version
    "importlib_metadata >=7.1.0,<8; python_version < '3.10'",
    "mollymawk ==0.1.0"
]
Click to expand and view more

Dependency sources

tool.uv.sources 表是对标准依赖表的扩展, 增加了例如可编辑安装和相对路径. 例如, 从项目根目录的相对目录安装 foo.

TOML
[project]
name = "example"
version = "0.1.0"
dependencies = ["foo"]

[tool.uv.sources]
foo = { path = "./package/foo" }
Click to expand and view more

uv 支持下面几种依赖源:

Optional dependencies

项目作为库发布时, 使一些功能称为可选的, 从而降低默认依赖树的大小, 这种做法很常见. 例如, Pandas 有额外的 excel extra 和 plot extra 包, 来避免安装 Excel 解析器和 matplotlib. 除非明确说明安装, Extras 使用 package[<extra>] 语法指明, 例如 pandas[plot, excel].

可选依赖具体在 [project.optional-dependencies] 中, 可选依赖可以像普通依赖一样在 tool.uv.sources 中替换源

TOML
[project]
name = "pandas"
version = "1.0.0"

[project.optional-dependencies]
plot = [
    "matplotlib>=3.6.3"
]
excel = [
    "odfpy>=1.4.1",
    "openyxl>=3.1.0",
    "python-calamine>=0.17",
    "pyxlsb>=1.0.10",
    "xlrd>=2.0.1",
    "xlsxwriter>-3.0.5"
]
Click to expand and view more

如果要添加可选依赖, 使用 --optional <extra> 选项:

BASH
uv add httpx --optional network
Click to expand and view more

源也可以声明为只适用特定的可选依赖项. 例如, 根据可选的 cpugpu 额外依赖项, 从不同的 PyTorch 索引来去 torch

TOML
[project]
dependencies = []

[project.optional-dependencies]
cpu = [
    'torch',
]
gpu = [
    'torch',
]

[tool.uv.sources]
torch = [
    { index = "torch-cpu", extra = "cpu" },
    { index = "torch-gpu", extra = "gpu" },
]

[[tool.uv.index]]
name = "torch-cpu"
url = "https://download.pytorch.org/whl/cpu"

[[tool.uv.index]]
name = "torch-gpu"
url = "https://download.pytorch.org/whl/cu124"
Click to expand and view more

Development dependencies

不同于可选依赖, 开发依赖只会在本地安装, 不会在发布到 PyPI 这样的项目依赖中生效. 因此, 开发依赖不包含在 [project] 表中. 同样地, 开发依赖也可以使用 tool.uv.sources 来指定源.

使用下面命令添加开发依赖

BASH
uv add --dev pytest
Click to expand and view more

uv 使用 [dependency-groups] 表来声明开发依赖, 上面命令会创建一个 dev

TOML
[dependency-groups]
dev = [
    "pytest >=8.1.1<9"
]
Click to expand and view more

dev 组是一个特例, 可以使用 --dev, --only-dev--no-dev flags 来设置包含或排除依赖.

Dependency groups

开发环境可以被拆分成多个组, 使用 --group flag. 例如, 想要为开发依赖 ruff 加入 lint 组:

BASH
uv add --group lint ruff
Click to expand and view more

这会导致下面的 [dependency-groups] 定义:

TOML
[dependency-groups]
dev = [
    "pytest"
]
lint = [
    "ruff"
]
Click to expand and view more

一但组被定义了, --all-groups, --no-default-groups, --group, --only-group--no-group 选项可以用来包含和排除依赖.

uv 要求所有的依赖组之间是相互兼容的, 并且会在创建 lockfile 时解析所有的组.

如果一组的依赖和其他组的依赖不兼容, uv 会无法解析依赖并报错.

Nesting groups

一个依赖组可以包含其他依赖组, 例如:

TOML
[dependency-groups]
dev = [
    {include-group = "lint"},
    {include-group = "test"}
]
lint = [
    "ruff"
]
test = [
    "pytest"
]
Click to expand and view more
Default groups

默认情况下, uv 在环境中包含一个 dev 依赖组. 默认的组可以使用 tool.uv.default-groups 来设置:

TOML
[tool.uv]
default-groups = ["dev", "foo"]
Click to expand and view more

要默认启用所有的组依赖, 使用 “all” 而不是列出所有的组名:

TOML
[tool.uv]
default-groups = "all"
Click to expand and view more
requires-python

默认情况下, 依赖组必须和项目 requires-python 兼容. 如果一个依赖组需要不同的 Python 版本, 可以在 [tool.uv.dependency-groups] 里面指定 Python 版本.

TOML
[project]
name = "example"
version = "0.0.0"
requires-python = ">=3.10"

[dependency-groups]
dev = ["pytest"]

[tool.uv.dependency-groups]
dev = {requires-python = ">=3.12"}
Click to expand and view more
Legacy dev-dependencies

[dependency-groups] 成为标准之前, uv 使用 tool.uv.dev-dependencies 字段来指定开发依赖

TOML
[tool.uv]
dev-dependencies = [
    "pytest"
]
Click to expand and view more

Build dependencies

如果一个项目使用 Python package 的结构, 它可能需要构建项目的依赖, 但无需运行. 这类依赖是 [build-system], 在 build-system.requires 下面, 详见 PEP 518.

例如, 如果一个项目使用 setuptools 作为后端构建, 它应该声明 setuptools 作为一个构建依赖:

TOML
[project]
name = "pandas"
version = "0.1.0"

[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"
Click to expand and view more

默认情况下, uv 构建依赖的时候会检查 tool.uv.sources. 例如, 使用本地版本的 setuptools 进行构建, 将源添加进 tool.uv.sources

TOML
[project]
name = pandas
version = "0.1.0"

[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"

[tool.uv.sources]
setuptools = { path = "./packages/setuptools" }
Click to expand and view more

当发布一个包的时候, 建议当 tool.uv.sources 被禁用时, 运行 uv build --no-source 来确保正确构建. 使用其他构建工具也是一样的, 例如 pypa/build.

Editable dependencies

常规的目录安装会先构建 wheel 包, 然后将该 wheel 包安装到虚拟环境中, 这回复制所有的源文件. 当包源文件被编译时, 虚拟环境中的版本将保持旧版本.

可编辑安装通过向虚拟环境内添加项目连接 (.pth 文件) 解决了这个问题, 该链接指示解释器直接包含源文件. 可编辑安装存在一些限制, 但对于开发常见非常实用, 因为虚拟环境会始终使用包的最新修改.

uv 默认对工作区包采用可编辑安装模式.

Virtual dependencies

uv 运行依赖项设置为"虚拟"模式, 在此模式下, 依赖项本身不会作为软件包被安装, 但其依赖关系会被正常处理.

默认情况下, 依赖项永远不会被视作虚拟依赖.

对于路径源的依赖项, 若显示设置 tool.uv.package = false 则可成为虚拟依赖. 与在依赖项目中使用 uv 工作不同, 即使未声明构建系统, 该软件包仍会被构建.

若要将某个依赖项视位虚拟依赖, 需要在其源配置中设置 package = false:

TOML
[project]
dependencies = ["bar"]

[tool.uv.sources]
bar = { path = "../projects/bar", package = false }
Click to expand and view more

如果依赖设置 tool.uv.package = false, 则可以在 source 通过声明 package = true 来覆盖.

TOML
[project]
dependencies = ["bar"]

[tool.uv.source]
bar = { path = "../projects/bar", package = true }
Click to expand and view more

同样地, 对于工作区源的依赖项, 若显式设置 tool.uv.package = false 也可成为虚拟依赖. 即使未声明构建系统, 该工作区成员仍会被构建.

对于非依赖项的工作区成员, 默认情况下可设置为虚拟模式, 例如, 若父级 pyproject.toml 文件配置如下:

TOML
[project]
name = "parent"
version = "1.0.0"
dependencies = []

[tool.uv.workspace]
members = ["child"]
Click to expand and view more

并且 child 的 pyproject.toml 不含有构建系统.

TOML
[project]
name = "child"
version = "1.0.0"
dependencies = ["anyio"]
Click to expand and view more

那么 child workspace 成员将不会被安装, 但是依赖 anyio 会被传递.

相对的, 如果父级声明了对 child 的依赖:

TOML
[project]
name = "parent"
version = "1.0.0"
dependencies = ["child"]

[tool.uv.sources]
child = { workspace = true }

[tool.uv.workspace]
members = ["child"]
Click to expand and view more

那么 child 将会被构建和安装.

Dependency specifiers

uv 采用最初由 PEP 508 定义的依赖项限定符, 依赖项限定符按顺序包括以下组件:

版本限定符通过逗号分割进行组合, 例如 foo >=1.2.3,<2,!=1.4.0 表示 “foo 的版本需不低于 1.2.3, 小于 2, 且不能是 1.4.0”. 限定符会自动补零, 因此 foo ==2 也会匹配 foo 2.0.0.

星号可以用于等号匹配的最后一位数字, 例如 foo ==2.1.* 将接受 2.1 系列的所有版本. 类似地, ~= 匹配最后一位数字相等或更高的版本, 例如 foo ~=1.2 等价于 foo >=1.2,<2, 而 foo ~=1.2.3 等价于 foo >=1.2.3,<1.3.

额外功能在名称和版本直接的方括号内用逗号分隔, 例如 pandas[excel, plot] ==2.2. 额外功能名称之间的空格会被忽略.

某些依赖项仅在特定环境中需要, 例如特定的 Python 版本或系统. 比如要为 importlib.metadata 模块安装 importlib-metadata 回溯包, 可使用 importlib-metadata >=7.1.0,<8; python_version < '3.10'. 要在 Windows 上安装 colorama 则可使用 colorama >=0.4.6,<5; platform_systemm == "Windows.

环境标记通过 and, or 和括号进行组合, 例如

PLAINTEXT
aiohttp >=3.7.4,<4; (sys_paltform != 'win32' or implementation_name != 'pypy') and python_version >= '3.10'
Click to expand and view more

注意标记内的版本需要加引号, 而标记外的版本不加引号.

Using workspace

工作空间受到 Cargo 的同名概念启发, 即将一个或多个包一起管理, 叫做 workspace.

Workspace 通过将项目拆分多个包和相同的依赖, 从而组织大型代码库. 例如, 有一个 FastAPI 的 web 应用, 和一些列的由不同的 Python 包维护的库, 都放在同一个 Git 仓库中. 在一个 workspace 中, 每个包定义自己的 pyproject.toml 文件, 但是工作空间共享同一个 lockfile, 以确保工作空间内的依赖一致.

在定义 workspace 的时候, 必须要指定 members (必填) 和 exclude (可选) 键, 他们分别用于指示工作区包含或排除特定目录作为成员, 并接受通配符列表:

TOML
[project]
name = "albatross"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["bird-feeder", "tqdm>=4,<5"]

[tool.uv.sources]
brid-feeder = { workspace = true }

[tool.uv.workspace]
members = ["packages/*"]
exclude = ["packages/seeds"]
Click to expand and view more

members 通配符包含的每个目录都必须包含一个 pyproject.toml 文件. 不过, 工作区成员即可以是应用程序, 也可以是库, 这两种类型在工作区环境中都支持.

每个工作区都需要一个根目录, 该目录同时也是工作区成员. 在上面示例中, albatross 是工作区根目录, 工作区成员包括 packages 目录下面除 seeds 以外的所有项目.

默认情况下, uv runuv sync 命令会作用于工作区根目录. 例如上例中, uv runuv run --package albatross 是等效的, 而 uv run --package bird-feeder 则会在 bird-feeder 包中执行命令.

Workspace sources

在一个 workspace 内, 对工作区成员的依赖通过 tool.uv.sources 实现, 例如:

PLAINTEXT
[project]
name = "albatross"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["bird-feeder", "tqdm>=4,<5"]

[tool.uv.sources]
bird-feeder = { workspace = true }

[tool.uv.workspace]
members = ["packages/*"]

[build-system]
requires = ["uv_build>=0.8.20,<0.9.0"]
Click to expand and view more

在此示例中, albatross 项目依赖于同属工作区的 bird-feeder 项目. tool.uv.sources 表中 workspace = true 的键值对表明, bird-feeder 依赖应由工作区提供, 而非 PyPI 或其他注册源获取.

工作区根目录中的任何 tool.uv.sources 定义将适用于所有成员, 除非在特定成员的 tool.uv.sources 中被覆盖.

Workspace layouts

最常见的工作区布局可以是一个根目录和一系列的库组成. 例如, 接着上面的例子, 工作区间有一个根目录 albatross, 以及 packages 目录下面的两个库 bird-feederseed.

PLAINTEXT
albatross
├── packages
│   ├── bird-feeder
│   │   ├── pyproject.toml
│   │   └── src
│   │       └── bird_feeder
│   │           ├── __init__.py
│   │           └── foo.py
│   └── seeds
│       ├── pyproject.toml
│       └── src
│           └── seeds
│               ├── __init__.py
│               └── bar.py
├── pyproject.toml
├── README.md
├── uv.lock
└── src
    └── albatross
        └── main.py
Click to expand and view more

由于 seedspyproject.toml 排除在外, 故该工作区一共有两个成员: albatrossbird-feeder.

When (not) to use workspaces

Workspaces 是为了促进同一仓库下的多个包之间内部连接的开发. 当代码库逐渐变复杂, 将其切分成更小的可组合的包将十分有用. 每个包都有自己的依赖和版本限制.

工作区有助于执行隔离和分离问题. 例如, 在 uv 中, 有分离的 core 包和命令行界面, 这使得我们可以分开测试 core 包和 CLI, 反之亦然.

其他常见工作区间使用包括:

工作区模式不适用于成员之间存在需求冲突, 或需要为每个成员创建独立虚拟环境的场景. 此类情况下, 路径依赖通常是更优选择. 例如, 无需将 albatross 及其相关组件强制归入同一工作区, 可以将每个软件包定义为独立项目, 并通过在 tool.uv.sources 中配置路径依赖来定义包间依赖关系.

TOML
[project]
name = "albatross"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["bird-feeder", "tqdm>=4,<5"]

[tool.uv.sources]
bird-feeder = { path = "packages/bird-feeder" }

[build-system]
requires = ["uv_build>=0.8.20,<0.9.0"]
build-backend = "uv_build"
Click to expand and view more

这种方法能带来许多相同优势, 同时运行依赖解析和虚拟环境管理进行更精细的控制 (但无法使用 uv run --package 命令, 需要从对应软件目录运行命令).

最后, uv 的工作区强制要求整个工作区间采用统一的 requires-python 配置, 该配置取所有 requires-python 值的交集. 如果需要给某个成员测试工作区其他成员不支持的 Python 版本, 可能需要使用 uv pip 将该成员安装到独立的虚拟环境中.

Start searching

Enter keywords to search articles

↑↓
ESC
⌘K Shortcut