跳到内容

包索引

默认情况下,uv 使用 Python 包索引 (PyPI) 进行依赖解析和包安装。然而,可以通过 [[tool.uv.index]] 配置选项(以及对应的命令行选项 --index)将 uv 配置为使用其他包索引,包括私有索引。

定义索引

若要在解析依赖项时包含额外索引,请在 pyproject.toml 中添加 [[tool.uv.index]] 条目:

[[tool.uv.index]]
# Optional name for the index.
name = "pytorch"
# Required URL for the index.
url = "https://download.pytorch.org/whl/cpu"

索引按定义的先后顺序确定优先级,即配置文件中列出的第一个索引是解析依赖项时首先查询的索引,通过命令行提供的索引优先级高于配置文件中的索引。

默认情况下,uv 将 Python 包索引 (PyPI) 作为“默认”索引,即当在任何其他索引中都找不到包时使用的索引。要从索引列表中排除 PyPI,请在另一个索引条目中设置 default = true(或使用 --default-index 命令行选项)。

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

无论默认索引在索引列表中的位置如何,它始终被视为最低优先级。

索引名称只能包含字母数字字符、连字符、下划线和点号,且必须是有效的 ASCII 字符。

当在命令行(使用 --index--default-index)或通过环境变量(UV_INDEXUV_DEFAULT_INDEX)提供索引时,名称是可选的,但可以使用 <name>=<url> 语法包含名称,例如:

# On the command line.
$ uv lock --index pytorch=https://download.pytorch.org/whl/cpu
# Via an environment variable.
$ UV_INDEX=pytorch=https://download.pytorch.org/whl/cpu uv lock

将包锁定到特定索引

可以通过在 tool.uv.sources 条目中指定索引,将包锁定到特定索引。例如,为了确保 torch 始终pytorch 索引安装,请将以下内容添加到 pyproject.toml 中:

[tool.uv.sources]
torch = { index = "pytorch" }

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

同样,为了根据平台从不同索引获取包,你可以提供一个由环境标记区分的源列表:

pyproject.toml
[project]
dependencies = ["torch"]

[tool.uv.sources]
torch = [
  { index = "pytorch-cu118", marker = "sys_platform == 'darwin'"},
  { index = "pytorch-cu124", marker = "sys_platform != 'darwin'"},
]

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

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

可以将索引标记为 explicit = true,以防止包从该索引安装,除非明确将其锁定到该索引。例如,为了确保 torchpytorch 索引安装,而所有其他包从 PyPI 安装,请将以下内容添加到 pyproject.toml 中:

[tool.uv.sources]
torch = { index = "pytorch" }

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

通过 tool.uv.sources 引用的命名索引必须在项目的 pyproject.toml 文件中定义;通过命令行、环境变量或用户级配置提供的索引将无法识别。

如果一个索引同时被标记为 default = trueexplicit = true,它将被视为显式索引(即只能通过 tool.uv.sources 使用),同时会移除 PyPI 作为默认索引。

跨多个索引搜索

默认情况下,uv 会在找到给定包的第一个索引处停止搜索,并将解析限制为仅存在于该第一个索引中的版本(first-index)。

例如,如果通过 [[tool.uv.index]] 指定了一个内部索引,uv 的行为是:如果某个包存在于该内部索引中,它将始终从该内部索引安装,而从不从 PyPI 安装。其目的是防止“依赖混淆(dependency confusion)”攻击,即攻击者在 PyPI 上发布与内部包同名的恶意包,从而导致系统安装了恶意包而非内部包。请参阅 2022 年 12 月发生的 torchtriton 攻击案例。

若要选择替代索引行为,请使用 --index-strategy 命令行选项或 UV_INDEX_STRATEGY 环境变量,它们支持以下值:

  • first-index(默认):跨所有索引搜索每个包,并将候选版本限制为包含该包的第一个索引中存在的版本。
  • unsafe-first-match:跨所有索引搜索每个包,但优先选择具有兼容版本的第一个索引,即使其他索引上有更新的版本。
  • unsafe-best-match:跨所有索引搜索每个包,并从所有候选版本的集合中选择最佳版本。

虽然 unsafe-best-match 最接近 pip 的行为,但它使用户面临“依赖混淆”攻击的风险。

身份验证

大多数私有包索引需要身份验证才能访问包,通常通过用户名和密码(或访问令牌)实现。

提示

有关使用特定私有索引提供程序(例如 AWS、Azure 或 GCP)进行身份验证的详细信息,请参阅替代索引指南

直接提供凭据

凭据可以直接通过环境变量提供,或者通过将它们嵌入到 URL 中提供。

例如,假设有一个名为 internal-proxy 的索引,它需要用户名 (public) 和密码 (koala),请在 pyproject.toml 中定义该索引(不含凭据):

[[tool.uv.index]]
name = "internal-proxy"
url = "https://example.com/simple"

此后,你可以设置 UV_INDEX_INTERNAL_PROXY_USERNAMEUV_INDEX_INTERNAL_PROXY_PASSWORD 环境变量,其中 INTERNAL_PROXY 是索引名称的大写版本,且非字母数字字符替换为下划线:

export UV_INDEX_INTERNAL_PROXY_USERNAME=public
export UV_INDEX_INTERNAL_PROXY_PASSWORD=koala

通过环境变量提供凭据,可以避免将敏感信息存储在纯文本的 pyproject.toml 文件中。

或者,凭据也可以直接嵌入到索引定义中:

[[tool.uv.index]]
name = "internal"
url = "https://public:[email protected]/simple"

出于安全考虑,凭据永远不会存储在 uv.lock 文件中;因此,uv 必须在安装时能够访问经过身份验证的 URL。

使用凭据提供程序

除了直接提供凭据外,uv 还支持从 netrc 和 keyring 中发现凭据。有关设置特定凭据提供程序的详细信息,请参阅 HTTP 身份验证文档。

默认情况下,uv 会在查询提供程序之前尝试进行未经验证的请求。如果请求失败,uv 将搜索凭据。如果找到了凭据,将尝试进行已验证的请求。

注意

如果设置了用户名,uv 将在发出未验证请求之前搜索凭据。

某些索引(例如 GitLab)会将未验证的请求转发到公共索引(如 PyPI)——这意味着 uv 将不会搜索凭据。此行为可以针对每个索引进行更改,使用 authenticate 设置。例如,始终搜索凭据:

[[tool.uv.index]]
name = "example"
url = "https://example.com/simple"
authenticate = "always"

authenticate 设置为 always 时,uv 将主动搜索凭据,如果找不到凭据则会报错。

跨索引搜索时忽略错误代码

当使用 first-index 策略时,如果遇到 HTTP 401 Unauthorized 或 HTTP 403 Forbidden 状态码,uv 将停止跨索引搜索。唯一的例外是,当搜索 pytorch 索引时,uv 会忽略 403 错误(因为该索引在包不存在时会返回 403)。

要配置索引忽略哪些错误代码,请使用 ignored-error-codes 设置。例如,忽略私有索引的 403 错误(但不忽略 401):

[[tool.uv.index]]
name = "private-index"
url = "https://private-index.com/simple"
authenticate = "always"
ignore-error-codes = [403]

当遇到 404 Not Found 时,uv 将始终继续跨索引搜索。此行为无法被覆盖。

禁用身份验证

为防止泄露凭据,可以禁用索引的身份验证:

[[tool.uv.index]]
name = "example"
url = "https://example.com/simple"
authenticate = "never"

authenticate 设置为 never 时,uv 将永远不会为给定索引搜索凭据,如果直接提供了凭据,则会报错。

自定义缓存控制标头

默认情况下,uv 会遵循索引提供的缓存控制标头。例如,PyPI 提供带有 max-age=600 标头的包元数据,从而允许 uv 将包元数据缓存 10 分钟;并提供带有 max-age=365000000, immutable 标头的 Wheel 和源代码分发包,从而允许 uv 无限期缓存这些工件。

要覆盖索引的缓存控制标头,请使用 cache-control 设置:

[[tool.uv.index]]
name = "example"
url = "https://example.com/simple"
cache-control = { api = "max-age=600", files = "max-age=365000000, immutable" }

cache-control 设置接受一个包含两个可选键的对象:

  • api:控制 Simple API 请求(包元数据)的缓存。
  • files:控制工件下载(Wheel 和源代码分发包)的缓存。

这些键的值是遵循 HTTP Cache-Control 语法的字符串。例如,要强制 uv 始终重新验证包元数据,请设置 api = "no-cache"

[[tool.uv.index]]
name = "example"
url = "https://example.com/simple"
cache-control = { api = "no-cache" }

此设置最常用于覆盖私有索引的默认缓存控制标头,这些索引有时会无意中禁用缓存。我们通常建议遵循 PyPI 的缓存标头方法,即设置 api = "max-age=600"files = "max-age=365000000, immutable"

“平面(Flat)”索引

默认情况下,[[tool.uv.index]] 条目被假定为实现 PEP 503 简单存储库 API 的 PyPI 风格注册表。然而,uv 也支持“平面(flat)”索引,即包含 Wheel 和源代码分发包平面列表的本地目录或 HTML 页面。在 pip 中,此类索引使用 --find-links 选项指定。

要在 pyproject.toml 中定义一个平面索引,请使用 format = "flat" 选项:

[[tool.uv.index]]
name = "example"
url = "/path/to/directory"
format = "flat"

平面索引支持与简单存储库 API 索引相同的功能集(例如 explicit = true);你也可以使用 tool.uv.sources 将包锁定到平面索引。

--index-url--extra-index-url

除了 [[tool.uv.index]] 配置选项外,为了兼容性,uv 还支持 pip 风格的 --index-url--extra-index-url 命令行选项,其中 --index-url 定义默认索引,--extra-index-url 定义附加索引。

这些选项可以与 [[tool.uv.index]] 配置选项结合使用,并遵循相同的优先级规则。

  • 默认索引始终被视为最低优先级,无论是通过旧版 --index-url 参数、推荐的 --default-index 参数,还是通过设置了 default = true[[tool.uv.index]] 条目定义的。
  • 索引会按照它们定义的顺序进行查询,无论是通过旧版 --extra-index-url 参数、推荐的 --index 参数,还是通过 [[tool.uv.index]] 条目。

实际上,--index-url--extra-index-url 可以被视为未命名的 [[tool.uv.index]] 条目,前者启用了 default = true。在这种语境下,--index-url 映射到 --default-index--extra-index-url 映射到 --index