Python 3.12+ 报 No module named 'distutils':三种恢复姿势

Python 3.13 环境下跑 labelImg,直接崩:

File ".../site-packages/labelImg/labelImg.py", line 5, in <module>
    import distutils.spawn
ModuleNotFoundError: No module named 'distutils'

uv / pip 装依赖时也可能顺带看到:

Because there are no versions of distutils and you require distutils,
we can conclude that your requirements are unsatisfiable.

为什么消失了

distutils 从 Python 3.10 就被标注 deprecated,3.12 起彻底删除。它的角色被 setuptoolspackaging 接管,但很多老库(labelImg、部分 setup.py、老工具链)里还是硬 import distutils.spawndistutils.util

方案一:让 setuptools 顶上

从 setuptools 60 开始,装 setuptools 时会顺手把 distutils 兼容层装回来:

pip install --upgrade setuptools

装完再跑一次原命令,八成的老库都能过。注意要装到 触发报错的那个 Python 里,虚拟环境别搞混。

方案二:改一行源码(最彻底)

distutils.spawn.find_executable 其实就等价于 shutil.which。找到出错的文件:

.venv\Lib\site-packages\labelImg\labelImg.py

把顶部的:

import distutils.spawn

替换成:

import shutil

然后把用到的地方:

distutils.spawn.find_executable("xxx")
# 改成
shutil.which("xxx")

一处不会漏。这个改法在 CI 环境里最省事——不用装额外依赖。

方案三:降回 3.11(保稳)

赶时间又不想改源码:

py -3.11 -m venv .venv311
.\.venv311\Scripts\activate
pip install labelImg
labelImg

3.11 保留 distutils,官方支持到 2027 年 10 月,够用很久。

三种方案怎么选

场景推荐
自己项目、能改源码方案二(shutil.which
老工具/labelImg 类第三方包方案一 + 方案三兜底
生产环境、要稳方案三(Python 3.11)

一句话总结

distutils 3.12 起被删。八成情况装 setuptools 就能过;不行就直接改 shutil.which;最保险的是回 Python 3.11。