You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在pip安装Python包时仅安装核心依赖(反向实现setuptools的extras_require功能)

实现反向依赖安装:默认全量,指定参数装核心

刚好碰到过类似的需求——给内部包做适配时,既要保证大部分用户装完就能用全功能,又要给少数需要轻量安装的用户留口子。整理了几个亲测有效的方案,按需选就行:

方案1:反向利用extras_require(最贴合pip生态)

这个是最推荐的,完全符合pip的使用习惯,用户只需要敲pip install mypackage[core]就能装核心版本,默认还是全量依赖。

核心思路是:把完整依赖设为默认,然后通过core extras来排除掉那些重型/非必要依赖。需要注意的是这个方法要求pip版本≥21.0(现在大部分环境都满足),因为用到了pip的依赖排除语法。

pyproject.toml(现代Python包推荐写法):

[project]
name = "mypackage"
version = "0.1.0"
# 默认安装完整依赖集
dependencies = [
  "requests>=2.25.0",  # 核心依赖
  "click>=8.0",        # 核心依赖
  "pandas>=1.3",       # 重型依赖
  "numpy>=1.21"        # 重型依赖
]

[project.extras]
# core选项:排除重型依赖,只保留核心
core = [
  "mypackage@.",  # 引用当前包
  "-pandas",      # 排除pandas
  "-numpy"        # 排除numpy
]

当用户执行pip install mypackage[core]时,pip会自动处理依赖:先拉取默认的全量依赖,然后移除指定的重型包,最终只留下核心依赖。

方案2:环境变量+动态依赖判断(兼容老版本pip)

如果你的用户还有用老版本pip的(比如<21.0),这个方案兼容性拉满,逻辑也简单。

setup.py里通过环境变量判断要装的依赖集:

from setuptools import setup
import os

# 核心依赖:无论哪种安装方式都必须有的
CORE_DEPS = [
    "requests>=2.25.0",
    "click>=8.0"
]

# 完整依赖:核心+重型依赖
FULL_DEPS = CORE_DEPS + [
    "pandas>=1.3",
    "numpy>=1.21"
]

# 根据环境变量切换:设置INSTALL_CORE=1就装核心依赖,否则装全量
install_deps = CORE_DEPS if os.getenv("INSTALL_CORE") else FULL_DEPS

setup(
    name="mypackage",
    version="0.1.0",
    install_requires=install_deps,
    # 其他包配置(比如entry_points、packages等)
)

用户装核心版本时只要加个环境变量就行:

INSTALL_CORE=1 pip install mypackage

这个方法我之前给公司的老项目用过,完全没兼容性问题,就是用户需要记一下环境变量,不如方括号语法直观。

方案3:自定义安装命令(支持--core-option形式)

如果你特别想要用户用类似pip install --core-option mypackage的语法,可以自定义一个安装命令。不过这个方法稍微复杂点,而且从PyPI安装时会有安全提示(因为用到了--global-option),适合内部包用。

setup.py里写自定义命令:

from setuptools import setup, Command

class InstallCoreCommand(Command):
    """自定义命令:仅安装核心依赖"""
    description = "Install mypackage with only core dependencies"
    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        # 把依赖替换成核心依赖
        self.distribution.install_requires = [
            "requests>=2.25.0",
            "click>=8.0"
        ]
        # 调用默认的install命令执行安装
        from setuptools.command.install import install
        install_cmd = install(self.distribution)
        install_cmd.initialize_options()
        install_cmd.finalize_options()
        install_cmd.run()

setup(
    name="mypackage",
    version="0.1.0",
    # 默认全量依赖
    install_requires=[
        "requests>=2.25.0",
        "click>=8.0",
        "pandas>=1.3",
        "numpy>=1.21"
    ],
    cmdclass={
        'install_core': InstallCoreCommand
    }
)

用户安装核心版本时执行:

# 本地安装
pip install . --install-option=install_core

# 从PyPI安装(会有安全提示,因为修改了全局选项)
pip install mypackage --global-option=install_core

方案选择建议

  • 优先选方案1:符合pip生态,用户学习成本低,只要会用extras的人一看就懂。
  • 老环境兼容选方案2:没有pip版本限制,逻辑简单可靠。
  • 非要自定义命令选方案3:满足--core-option的需求,但体验不如前两个。

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

火山引擎 最新活动