构建失败故障排除
当没有兼容的 wheel(预构建的软件包发行版)时,uv 需要构建软件包。构建软件包可能因多种原因失败,其中一些原因可能与 uv 本身无关。
识别构建失败
尝试在不受支持的新版 Python 上安装旧版本的 numpy 时,可能会出现构建失败示例:
$ uv pip install -p 3.13 'numpy<1.20'
在 62 毫秒内解析了 1 个软件包
× 未能构建 `numpy==1.19.5`
├─▶ 构建后端返回错误
╰─▶ 调用 `setuptools.build_meta:__legacy__.build_wheel()` 失败(退出状态:1)
[stderr]
追溯(最近一次调用最后):
文件 "<string>",第 8 行,在 <module> 中
from setuptools.build_meta import __legacy__ as backend
文件 "/home/konsti/.cache/uv/builds-v0/.tmpi4bgKb/lib/python3.13/site-packages/setuptools/__init__.py",第 9 行,在 <module> 中
import distutils.core
ModuleNotFoundError: 没有名为 'distutils' 的模块
提示:`distutils` 在 Python 3.12 中已从标准库中移除。考虑添加约束条件(如 `numpy >1.19.5`),以避免构建依赖 `distutils` 的 `numpy` 版本。
构建失败信息包括用于构建的构建后端的 [stderr]
(如果有,还有 [stdout]
)。错误日志并非来自 uv 本身。
╰─▶
之后的消息是 uv 提供的提示,用于帮助解决常见的构建失败问题。并非所有构建失败都有提示。
确认构建失败是否特定于 uv
构建失败通常与您的系统和构建后端有关。特定于 uv 的构建失败情况很少见。您可以尝试使用 pip
重现该问题,以确认构建失败与 uv 无关:
$ uv venv -p 3.13 --seed
$ source .venv/bin/activate
$ pip install --use-pep517 --no-cache --force-reinstall 'numpy==1.19.5'
Collecting numpy==1.19.5
Using cached numpy-1.19.5.zip (7.3 MB)
Installing build dependencies ... done
Getting requirements to build wheel ... done
ERROR: Exception:
Traceback (most recent call last):
...
File "/Users/example/.cache/uv/archive-v0/3783IbOdglemN3ieOULx2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_impl.py", line 321, in _call_hook
raise BackendUnavailable(data.get('traceback', ''))
pip._vendor.pyproject_hooks._impl.BackendUnavailable: Traceback (most recent call last):
File "/Users/example/.cache/uv/archive-v0/3783IbOdglemN3ieOULx2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 77, in _build_backend
obj = import_module(mod_path)
File "/Users/example/.local/share/uv/python/cpython-3.13.0-macos-aarch64-none/lib/python3.13/importlib/__init__.py", line 88, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 1022, in exec_module
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "/private/var/folders/6p/k5sd5z7j31b31pq4lhn0l8d80000gn/T/pip-build-env-vdpjme7d/overlay/lib/python3.13/site-packages/setuptools/__init__.py", line 9, in <module>
import distutils.core
ModuleNotFoundError: No module named 'distutils'
Important
pip install
调用中应包含 --use-pep517
标志,以确保相同的构建隔离行为。uv 默认始终使用构建隔离。
我们还建议在重现失败时包含 --force-reinstall
和 --no-cache
选项。
由于此构建失败在 pip
中也会出现,因此不太可能是 uv 的 bug。
如果使用其他安装程序也能重现构建失败,您应该向上游(在此示例中为 numpy
或 setuptools
)进行调查,首先找到避免构建该软件包的方法,或者对您的系统进行必要调整以使构建成功。
为什么 uv 要构建软件包?
在生成跨平台锁定文件时,uv 需要确定所有软件包的依赖项,即使是那些仅安装在其他平台上的依赖项。uv 会在解析过程中尽量避免构建软件包。如果存在该版本的 wheel 文件,它会使用该文件,然后尝试在源发行版中查找静态元数据(主要是包含静态 project.version
、project.dependencies
和 project.optional-dependencies
的 pyproject.toml
文件,或 METADATA v2.2+)。只有在所有这些尝试都失败时,它才会构建软件包。
在安装时,uv 需要为每个软件包准备适用于当前平台的 wheel 文件。如果索引中不存在匹配的 wheel 文件,uv 会尝试构建源发行版。
你可以在 “下载文件” 下查看 PyPI 项目存在哪些 wheel 文件,例如 https://pypi.org/project/numpy/2.1.1.md#files。文件名中包含 ...-py3-none-any.whl
的 wheel 文件可在任何地方使用,其他 wheel 文件的文件名中则包含操作系统和平台信息。在链接的 numpy
示例中,你可以看到针对 MacOS、Linux 和 Windows 上的 Python 3.10 到 3.13 有预构建的发行版。
常见的构建失败情况
以下示例展示了常见的构建失败情况以及如何解决它们。
找不到命令
如果构建错误提示缺少某个命令,例如 gcc
:
× 未能构建 `pysha3==1.0.2`
├─▶ 构建后端返回错误
╰─▶ 调用 `setuptools.build_meta:__legacy__.build_wheel` 失败(退出状态码:1)
[标准输出]
运行 bdist_wheel
运行 build
运行 build_py
创建 build/lib.linux-x86_64-cpython-310
将 sha3.py 复制到 build/lib.linux-x86_64-cpython-310
运行 build_ext
构建 '_pysha3' 扩展
创建 build/temp.linux-x86_64-cpython-310/Modules/_sha3
gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -DPY_WITH_KECCAK=1 -I/root/.cache/uv/builds-v0/.tmp8V4iEk/include -I/usr/local/include/python3.10 -c
Modules/_sha3/sha3module.c -o build/temp.linux-x86_64-cpython-310/Modules/_sha3/sha3module.o
[标准错误输出]
错误:命令 'gcc' 失败:没有那个文件或目录
那么,你需要使用系统包管理器安装该命令,例如,要解决上述错误:
提示
使用 uv 管理的 Python 版本时,通常需要安装 clang
而非 gcc
。
许多 Linux 发行版提供了包含所有常见构建依赖项的软件包。你可以通过安装该软件包来满足大多数构建需求,例如,对于 Debian 或 Ubuntu:
缺少头文件或库
如果构建错误提示缺少头文件或库,例如某个 .h
文件,那么你需要使用系统包管理器来安装它。
例如,安装 pygraphviz
需要先安装 Graphviz:
× 未能构建 `pygraphviz==1.14`
├─▶ 构建后端返回错误
╰─▶ 调用 `setuptools.build_meta.build_wheel` 失败(退出状态码:1)
[标准输出]
运行 bdist_wheel
运行 build
运行 build_py
...
gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -DSWIG_PYTHON_STRICT_BYTE_CHAR -I/root/.cache/uv/builds-v0/.tmpgLYPe0/include -I/usr/local/include/python3.12 -c pygraphviz/graphviz_wrap.c -o
build/temp.linux-x86_64-cpython-312/pygraphviz/graphviz_wrap.o
[标准错误输出]
...
pygraphviz/graphviz_wrap.c:9: 警告:“SWIG_PYTHON_STRICT_BYTE_CHAR”重定义
9 | #define SWIG_PYTHON_STRICT_BYTE_CHAR
|
<命令行>: 注意:这是上一次定义的位置
pygraphviz/graphviz_wrap.c:3023:10: 致命错误:graphviz/cgraph.h:没有那个文件或目录
3023 | #include "graphviz/cgraph.h"
| ^~~~~~~~~~~~~~~~~~~
编译终止。
错误:命令“/usr/bin/gcc”以退出码 1 失败
提示:此错误可能表明你需要为 `pygraphviz@1.14` 安装提供“graphviz/cgraph.h”的库
要在 Debian 上解决此错误,你需要安装 libgraphviz-dev
包:
请注意,仅安装 graphviz
包是不够的,还需要安装开发头文件。
提示
要解决 Python.h
缺失的错误,请安装 python3-dev
包。
模块缺失或无法导入
如果构建错误提示导入失败,可以考虑禁用构建隔离。
例如,有些软件包在未将 pip
声明为构建依赖项的情况下,就假定 pip
可用:
× 未能构建 `chumpy==0.70`
├─▶ 构建后端返回错误
╰─▶ 调用 `setuptools.build_meta:__legacy__.build_wheel` 失败(退出状态码:1)
[stderr]
追溯(最近一次调用):
文件 “<string>”,第 9 行,在 <module> 中
ModuleNotFoundError: 没有名为 'pip' 的模块
在处理上述异常期间,发生了另一个异常:
追溯(最近一次调用):
文件 “<string>”,第 14 行,在 <module> 中
文件 “/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py”,第 334 行,在 get_requires_for_build_wheel 中
return self._get_build_requires(config_settings, requirements=[])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
文件 “/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py”,第 304 行,在 _get_build_requires 中
self.run_setup()
文件 “/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py”,第 522 行,在 run_setup 中
super().run_setup(setup_script=setup_script)
文件 “/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py”,第 320 行,在 run_setup 中
exec(code, locals())
文件 “<string>”,第 11 行,在 <module> 中
ModuleNotFoundError: 没有名为 'pip' 的模块
要解决此错误,先安装构建依赖项,然后针对该软件包禁用构建隔离:
请注意,你需要安装缺失的软件包(例如 pip
)以及该软件包的所有其他构建依赖项(例如 setuptools
)。
构建的是旧版本的软件包
如果在解析过程中某个软件包构建失败,且构建失败的版本比你想要使用的版本旧,可以尝试添加一个带有下限的约束条件(例如 numpy>=1.17
)。有时,由于算法限制,uv 解析器会尝试使用不合理的旧软件包来寻找合适的版本,而使用下限可以避免这种情况。
例如,在 Python 3.10 上解析以下依赖项时,uv 会尝试构建旧版本的 apache-beam
。
× Failed to build `apache-beam==2.0.0`
├─▶ The build backend returned an error
╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1)
[stderr]
...
添加下限约束,例如 apache-beam<=2.49.0,>2.30.0
,可以解决此构建失败问题,因为 uv 将避免使用旧版本的 apache-beam
。
也可以使用 constraints.txt
文件或constraint-dependencies
设置为间接依赖项定义约束条件。
使用了构建依赖的旧版本
如果某个软件包因 uv
选择了不兼容或过时的构建时依赖版本而无法构建,你可以专门对构建依赖实施约束。可以使用
build-constraint-dependencies
设置(或类似的 build-constraints.txt
文件)来确保 uv
选择给定构建需求的合适版本。
例如,#5551 中描述的问题可以通过指定一个排除 setuptools
版本 72.0.0
的构建约束来解决:
[tool.uv]
# 防止将 setuptools 72.0.0 版本用作构建依赖。
build-constraint-dependencies = ["setuptools!=72.0.0"]
因此,构建约束将确保在构建过程中任何需要 setuptools
的软件包都不会使用有问题的版本,从而避免因不兼容的构建依赖导致的构建失败。
软件包仅用于未使用的平台
如果由于从你无需支持的平台构建软件包而导致锁定失败,可以考虑将解析范围限制在你支持的平台上。
软件包并非支持所有 Python 版本
如果你支持大范围的 Python 版本,可以考虑使用标记,对较旧的 Python 版本使用较旧的版本,对较新的 Python 版本使用较新的版本。例如,numpy
一次仅支持四个 Python 次版本,因此,为了支持更广泛的 Python 版本,例如 Python 3.8 到 3.13,需要拆分 numpy
需求:
包仅在特定平台上可用
如果由于构建仅在其他平台上可用的包而导致锁定失败,你可以手动提供依赖元数据以跳过构建。uv 无法验证此信息,因此在使用此覆盖时指定正确的元数据非常重要。