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 起彻底删除。它的角色被 setuptools 和 packaging 接管,但很多老库(labelImg、部分 setup.py、老工具链)里还是硬 import distutils.spawn 或 distutils.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。
