跳到内容

配置项目

Python 版本要求

项目可以在 pyproject.tomlproject.requires-python 字段中声明项目支持的 Python 版本。

建议设置一个 requires-python

pyproject.toml
[project]
name = "example"
version = "0.1.0"
requires-python = ">=3.12"

Python 版本要求决定了项目中允许使用的 Python 语法,并影响依赖项版本的选择(它们必须支持相同的 Python 版本范围)。

入口点

入口点 是已安装包用于声明接口的官方术语。 这些包括

重要

使用入口点表需要定义一个 构建系统

命令行界面

项目可以在 pyproject.toml[project.scripts] 表中定义项目的命令行界面 (CLI)。

例如,要声明一个名为 hello 的命令,该命令调用 example 模块中的 hello 函数

pyproject.toml
[project.scripts]
hello = "example:hello"

然后,可以从控制台运行该命令

$ uv run hello

图形用户界面

项目可以在 pyproject.toml[project.gui-scripts] 表中定义项目的图形用户界面 (GUI)。

重要

这些与 命令行界面 仅在 Windows 上有所不同,在 Windows 上,它们由 GUI 可执行文件包装,因此可以在没有控制台的情况下启动。 在其他平台上,它们的行为相同。

例如,要声明一个名为 hello 的命令,该命令调用 example 模块中的 app 函数

pyproject.toml
[project.gui-scripts]
hello = "example:app"

插件入口点

项目可以在 pyproject.toml[project.entry-points] 表中定义用于插件发现的入口点。

例如,要将 example-plugin-a 包注册为 example 的插件

pyproject.toml
[project.entry-points.'example.plugins']
a = "example_plugin_a"

然后,在 example 中,插件将使用以下方式加载

example/__init__.py
from importlib.metadata import entry_points

for plugin in entry_points(group='example.plugins'):
    plugin.load()

注意

group 键可以是任意值,不需要包含包名或“plugins”。 但是,建议通过包名来命名该键,以避免与其他包发生冲突。

构建系统

构建系统决定了如何打包和安装项目。 项目可以在 pyproject.toml[build-system] 表中声明和配置构建系统。

uv 使用构建系统的存在来确定项目是否包含应安装在项目虚拟环境中的包。 如果未定义构建系统,uv 将不会尝试构建或安装项目本身,而只是安装其依赖项。 如果定义了构建系统,uv 将构建项目并将其安装到项目环境中。

可以向 uv init 提供 --build-backend 选项来创建具有适当布局的已打包项目。 可以向 uv init 提供 --package 选项来创建具有默认构建系统的已打包项目。

注意

虽然 uv 在没有构建系统定义的情况下不会构建和安装当前项目,但其他包中不需要存在 [build-system] 表。 出于历史原因,如果未定义构建系统,则使用 setuptools.build_meta:__legacy__ 来构建包。 您依赖的包可能不会显式声明其构建系统,但仍然可以安装。 同样,如果您 添加对本地项目的依赖项 或使用 uv pip 安装它,无论是否存在 [build-system] 表,uv 都会尝试构建和安装它。

构建系统选项

构建系统用于支持以下功能

  • 包括或排除发行版中的文件
  • 可编辑的安装行为
  • 动态项目元数据
  • 本机代码编译
  • 供应商共享库

要配置这些功能,请参阅您选择的构建系统的文档。

项目打包

正如在 构建系统 中所讨论的,Python 项目必须构建才能安装。 此过程通常称为“打包”。

如果您想执行以下操作,您可能需要一个包

  • 向项目添加命令
  • 将项目分发给他人
  • 使用 srctest 布局
  • 编写库

如果您正在执行以下操作,您可能不需要

  • 编写脚本
  • 构建一个简单的应用程序
  • 使用平面布局

虽然 uv 通常使用 构建系统 的声明来确定是否应打包项目,但 uv 还允许使用 tool.uv.package 设置来覆盖此行为。

设置 tool.uv.package = true 将强制构建项目并将其安装到项目环境中。 如果未定义构建系统,uv 将使用 setuptools legacy 后端。

设置 tool.uv.package = false 将强制构建项目包并将其安装到项目环境中。 uv 在与项目交互时将忽略声明的构建系统; 但是,uv 仍然会尊重构建项目的显式尝试,例如调用 uv build

项目环境路径

可以使用 UV_PROJECT_ENVIRONMENT 环境变量来配置项目虚拟环境路径(默认为 .venv)。

如果提供了相对路径,它将相对于工作区根目录解析。 如果提供了绝对路径,它将按原样使用,即不会为环境创建子目录。 如果提供的路径中不存在环境,uv 将创建它。

可以使用此选项写入系统 Python 环境,但不建议这样做。 uv sync 默认情况下将从环境中删除多余的包,因此可能会使系统处于损坏状态。

要定位系统环境,请将 UV_PROJECT_ENVIRONMENT 设置为 Python 安装的前缀。 例如,在基于 Debian 的系统中,这通常是 /usr/local

$ python -c "import sysconfig; print(sysconfig.get_config_var('prefix'))"
/usr/local

要定位此环境,您需要导出 UV_PROJECT_ENVIRONMENT=/usr/local

重要

如果提供了绝对路径并且该设置在多个项目中使用,则该环境将被每个项目中的调用覆盖。 建议仅在 CI 或 Docker 映像中的单个项目中使用此设置。

注意

默认情况下,uv 在项目操作期间不会读取 VIRTUAL_ENV 环境变量。 如果 VIRTUAL_ENV 设置为与项目环境不同的路径,将显示警告。 可以使用 --active 标志选择加入以尊重 VIRTUAL_ENV。 可以使用 --no-active 标志来消除警告。

构建隔离

默认情况下,uv 按照 PEP 517 中的规定,在隔离的虚拟环境中构建所有包。 一些包与构建隔离不兼容,无论是出于有意(例如,由于使用了大量的构建依赖项,最常见的是 PyTorch)还是无意(例如,由于使用了旧的打包设置)。

要禁用特定依赖项的构建隔离,请将其添加到 pyproject.toml 中的 no-build-isolation-package 列表

pyproject.toml
[project]
name = "project"
version = "0.1.0"
description = "..."
readme = "README.md"
requires-python = ">=3.12"
dependencies = ["cchardet"]

[tool.uv]
no-build-isolation-package = ["cchardet"]

在没有构建隔离的情况下安装包需要先将包的构建依赖项安装到项目环境中,然后再安装包本身。 这可以通过将构建依赖项和需要它们的包分离到不同的 extras 中来实现。 例如

pyproject.toml
[project]
name = "project"
version = "0.1.0"
description = "..."
readme = "README.md"
requires-python = ">=3.12"
dependencies = []

[project.optional-dependencies]
build = ["setuptools", "cython"]
compile = ["cchardet"]

[tool.uv]
no-build-isolation-package = ["cchardet"]

鉴于以上情况,用户将首先同步 build 依赖项

$ uv sync --extra build
 + cython==3.0.11
 + foo==0.1.0 (from file:///Users/crmarsh/workspace/uv/foo)
 + setuptools==73.0.1

然后是 compile 依赖项

$ uv sync --extra compile
 + cchardet==2.1.7
 - cython==3.0.11
 - setuptools==73.0.1

请注意,默认情况下,uv sync --extra compile 将卸载 cythonsetuptools 包。 要改为保留构建依赖项,请在第二次 uv sync 调用中同时包含两个 extras

$ uv sync --extra build
$ uv sync --extra build --extra compile

上面的某些包(如 cchardet)仅在 uv sync安装阶段需要构建依赖项。 其他包(如 flash-attn)甚至在解析阶段也需要它们的构建依赖项来解析项目的锁定文件。

在这种情况下,必须在使用较低级别的 uv pip API 运行任何 uv lockuv sync 命令之前安装构建依赖项。 例如,给定

pyproject.toml
[project]
name = "project"
version = "0.1.0"
description = "..."
readme = "README.md"
requires-python = ">=3.12"
dependencies = ["flash-attn"]

[tool.uv]
no-build-isolation-package = ["flash-attn"]

您可以运行以下命令序列来同步 flash-attn

$ uv venv
$ uv pip install torch setuptools
$ uv sync

或者,您可以通过 dependency-metadata 设置预先提供 flash-attn 元数据,从而无需在依赖项解析阶段构建包。 例如,要预先提供 flash-attn 元数据,请在您的 pyproject.toml 中包含以下内容

pyproject.toml
[[tool.uv.dependency-metadata]]
name = "flash-attn"
version = "2.6.3"
requires-dist = ["torch", "einops"]

提示

要确定 flash-attn 等包的包元数据,请导航到相应的 Git 存储库,或在 PyPI 上查找并下载包的源分发。 包要求通常可以在 setup.pysetup.cfg 文件中找到。

(如果包包含构建的分发,您可以解压缩它以找到 METADATA 文件;但是,构建的分发的存在将否定预先提供元数据的需要,因为它已经可以被 uv 使用。)

一旦包含,您可以再次使用两步 uv sync 流程来安装构建依赖项。 给定以下 pyproject.toml

pyproject.toml
[project]
name = "project"
version = "0.1.0"
description = "..."
readme = "README.md"
requires-python = ">=3.12"
dependencies = []

[project.optional-dependencies]
build = ["torch", "setuptools", "packaging"]
compile = ["flash-attn"]

[tool.uv]
no-build-isolation-package = ["flash-attn"]

[[tool.uv.dependency-metadata]]
name = "flash-attn"
version = "2.6.3"
requires-dist = ["torch", "einops"]

您可以运行以下命令序列来同步 flash-attn

$ uv sync --extra build
$ uv sync --extra build --extra compile

注意

tool.uv.dependency-metadata 中的 version 字段对于基于注册表的依赖项是可选的(省略时,uv 将假定元数据适用于该包的所有版本),但对于直接 URL 依赖项(如 Git 依赖项)是必需的

可编辑模式

默认情况下,项目将以可编辑模式安装,以便对源代码的更改立即反映在环境中。 uv syncuv run 都接受 --no-editable 标志,该标志指示 uv 以非可编辑模式安装项目。 --no-editable 旨在用于部署用例,例如构建 Docker 容器,在这种情况下,项目应包含在已部署的环境中,而不依赖于原始源代码。

冲突的依赖项

uv 需要一起解析所有项目依赖项,包括可选依赖项(“extras”)和依赖项组。 如果在一个部分中声明的依赖项与另一部分中的依赖项不兼容,uv 将无法解析项目要求并出现错误。

uv 支持显式声明冲突的依赖项组。 例如,要声明 optional-dependencyextra1extra2 不兼容

pyproject.toml
[tool.uv]
conflicts = [
    [
      { extra = "extra1" },
      { extra = "extra2" },
    ],
]

或者,要声明开发依赖项组 group1group2 不兼容

pyproject.toml
[tool.uv]
conflicts = [
    [
      { group = "group1" },
      { group = "group2" },
    ],
]

有关更多信息,请参阅 解析文档

有限的解析环境

如果您的项目支持更有限的平台或 Python 版本集,您可以通过 environments 设置限制已解析平台的集合,该设置接受 PEP 508 环境标记列表。 例如,要将锁定文件限制为 macOS 和 Linux,并排除 Windows

pyproject.toml
[tool.uv]
environments = [
    "sys_platform == 'darwin'",
    "sys_platform == 'linux'",
]

有关更多信息,请参阅 解析文档

必需的环境

如果您的项目必须支持特定的平台或 Python 版本,您可以通过 required-environments 设置将该平台标记为必需。 例如,要要求项目支持 Intel macOS

pyproject.toml
[tool.uv]
required-environments = [
    "sys_platform == 'darwin' and platform_machine == 'x86_64'",
]

required-environments 设置仅与不发布源分发包(如 PyTorch)相关,因为此类包只能安装在预构建的二进制分发包(wheels)集所涵盖的环境中。

有关更多信息,请参阅 解析文档