uv工作区的包和路径依赖有什么区别?

编程语言 2026-07-11

uv 有两种方式通过相对路径指定对某个包的依赖。要么使用一个 path 依赖,要么使用工作区成员:

[tool.uv.sources]
package_a = { path = "python_stuff/package_a" }
package_b = { workspace = true }

[tool.uv.workspace]
members = [
    "python_stuff/package_b",
]

它们之间有什么区别?我应该在什么情况下选择其中一种?

解决方案

问题的注释中链接的 文档 做得很好,解释了工作区(workspace)是做什么,但并未专门比较使用路径源与工作区的情况。

通常在同时积极开发多个包时,我会推荐使用工作区。当你手头有某个第三方包的本地源码分发(或wheel)需要使用时,就使用路径依赖。

据我所知,把路径源设为可编辑指向一个目录,以及使用工作区源,在功能上是等价的。如果你查看 uv.lock 文件,它们被以同样的方式包含。

构建

在构建时,通常不会引用 sources 表,因为依赖关系只是包含在产物中的元数据,除非某个包指定了PEP 517构建要求。在这种情况下,依赖项实际上必须安装到一个虚拟环境中,因此它们会受到 “安装” 部分的约束。

安装

安装是在运行诸如 uv syncuv run 之类的命令时发生。

我不是uv的开发者,但我相信在底层,uv在安装时会把路径源和工作区源都转换成类似于PEP 508的 URL形式的依赖。

默认情况下,工作区包以可编辑方式安装,这是安装时路径源与工作区源之间唯一显著的差异。当路径源被指定为可编辑时,底层的安装功能在两者之间是等价的。

那么使用工作区有什么好处?

首先,工作区成员其实并不一定要是依赖项。工作区的主要目标是为工作区内所有包创建一个共用的环境。也就是说,如果两个包都依赖某个Python包,它们将使用该包的相同版本。工作区成员不必被包含在 tool.uv.sources 表中,除非其他成员依赖它们。

如果问题专门涉及那些确实是本地依赖项(因此会进入 tool.uv.sources 表)的包,我能想到的区分这两种结构的唯一实际情况,是在 uv builduv sync、和 uv run 上的 --package 标志。这允许指定要构建/运行的特定工作区成员,这可能相关也可能不相关。

这其实很微小,但在包含工作区成员时也允许使用通配符匹配。如果把它们作为依赖,它们仍然必须被包含在 tool.uv.sources 表中,类似于路径源。我认为使用工作区更整洁,这样你就可以有一个包含大量工作区成员的目录,并像 packages/* 那样包含它。这样路径就不会到处散落在你的 pyproject.toml 里;如果包含你包的路径发生改变,你只需修改工作区成员那一行。

uv仍在积极开发和演进。我认为如果你的项目设计就是要与工作区结构相匹配(也就是你希望所有包共享一个锁定文件),那么没有理由不使用工作区。随着uv的发展,可能会有专门针对具有工作区结构的项目做出的决策;如果你使用路径源,某些新功能可能就不会适用于你。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章