如何在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




