You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让distutils包仅为构建类命令设置setup_requires?

解决distutils/setuptools中仅构建命令加载大依赖的问题

这确实是distutils/setuptools里一个挺烦人的坑——把体积大的依赖塞到setup_requires里的话,不管你跑啥命令(哪怕只是setup.py clean)都会先拉取编译这个依赖,完全违背了清理命令的初衷。我之前也遇到过类似情况,分享几个亲测有效的解决办法:

方法一:动态判断命令,按需设置setup_requires

核心思路是通过读取命令行参数,判断当前执行的是不是构建相关命令,只有在需要构建时才把大依赖加入setup_requires。代码示例如下:

import sys
from setuptools import setup

def main():
    # 定义需要加载构建依赖的命令集合
    build_related_commands = {
        'build', 'build_ext', 'install', 
        'bdist_wheel', 'bdist_egg', 'develop'
    }
    
    # 获取当前执行的命令(处理多参数场景,比如`setup.py build bdist_wheel`)
    current_commands = set(sys.argv[1:])
    needs_build = bool(current_commands & build_related_commands) or \
                  any(cmd.startswith('build') for cmd in sys.argv)
    
    setup_requires = []
    if needs_build:
        # 仅在构建时添加这个大依赖
        setup_requires = ['your-heavy-dependency-package']
    
    setup(
        name='your-awesome-package',
        version='1.0.0',
        setup_requires=setup_requires,
        # 其他必要参数:packages、ext_modules等
        packages=['your_package'],
        ext_modules=[...],  # 如果是C扩展之类的需要构建的模块
    )

if __name__ == '__main__':
    main()

关键细节:

  • 我们覆盖了常见的构建类命令:build(基础构建)、build_ext(编译扩展)、install(安装)、bdist_wheel(生成wheel包)等,你可以根据自己的需求调整这个集合。
  • 额外处理了以build开头的命令(比如自定义的build_custom),避免遗漏特殊场景。
  • 这种方式对pip install也友好:pip执行的是install命令,会自动触发依赖加载,不影响正常安装流程。

方法二:用pyproject.toml分离构建依赖(推荐现代项目使用)

如果你已经在使用PEP 517/518标准的构建流程,可以把构建依赖放到pyproject.toml中,这样只有在实际构建时才会安装这些依赖,而执行setup.py clean这类非构建命令时不会触发。

创建pyproject.toml文件,内容如下:

[build-system]
requires = ["setuptools", "wheel", "your-heavy-dependency-package"]
build-backend = "setuptools.build_meta"

注意事项:

  • 这种方式下,当你直接运行setup.py clean时,setuptools不会去安装build-system.requires里的依赖(因为不需要构建环境),完美解决你的问题。
  • 如果你还在维护老项目,可能需要先确认你的构建工具(比如pip版本)支持pyproject.toml(pip 19.0+已经完全支持)。

方法三:重载命令类(进阶用法)

如果你需要更精细的控制,可以重载distutils/setuptools的命令类,在特定命令执行前才安装依赖。比如重载build_ext命令:

from setuptools import setup
from setuptools.command.build_ext import build_ext
import subprocess
import sys

class CustomBuildExt(build_ext):
    def run(self):
        # 在执行扩展编译前,手动安装大依赖
        subprocess.check_call([sys.executable, "-m", "pip", "install", "your-heavy-dependency-package"])
        super().run()

setup(
    name='your-awesome-package',
    version='1.0.0',
    cmdclass={'build_ext': CustomBuildExt},
    # 其他参数...
)

这种方式的灵活性更高,但需要你对distutils的命令体系有一定了解,适合复杂场景。

内容的提问来源于stack exchange,提问作者skoy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:21:51