包索引
默认情况下,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 命令行选项)。
无论默认索引在索引列表中的位置如何,它始终被视为最低优先级。
索引名称只能包含字母数字字符、连字符、下划线和点号,且必须是有效的 ASCII 字符。
当在命令行(使用 --index 或 --default-index)或通过环境变量(UV_INDEX 或 UV_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"
同样,为了根据平台从不同索引获取包,你可以提供一个由环境标记区分的源列表:
[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,以防止包从该索引安装,除非明确将其锁定到该索引。例如,为了确保 torch 从 pytorch 索引安装,而所有其他包从 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 = true 和 explicit = 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 中定义该索引(不含凭据):
此后,你可以设置 UV_INDEX_INTERNAL_PROXY_USERNAME 和 UV_INDEX_INTERNAL_PROXY_PASSWORD 环境变量,其中 INTERNAL_PROXY 是索引名称的大写版本,且非字母数字字符替换为下划线:
通过环境变量提供凭据,可以避免将敏感信息存储在纯文本的 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 设置。例如,始终搜索凭据:
当 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 将始终继续跨索引搜索。此行为无法被覆盖。
禁用身份验证
为防止泄露凭据,可以禁用索引的身份验证:
当 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" 选项:
平面索引支持与简单存储库 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。