如何通过conda build、develop和pip实现Python包依赖的单一源管理?
解决Python包多依赖清单重复的方案
针对同时支持pip/setuptools和conda打包、且需要维护开发环境的场景,以下是几种实用的减少依赖重复的方法:
1. 单一核心依赖文件 + 模板生成配置
创建一个独立的YAML/JSON文件(比如dependencies.yaml)存储所有通用依赖,再通过简单脚本结合模板生成各个配置文件,彻底避免重复:
示例核心依赖文件 dependencies.yaml
# 通用运行依赖(pip和conda兼容) runtime_deps: - requests>=2.25.0 - pandas>=1.3.0 - numpy>=1.21.0 # 通用构建依赖 build_deps: - setuptools>=61.0 - wheel>=0.37.0 # Conda独有依赖(如果有) conda_only_deps: - libgfortran # 仅conda需要的系统依赖 # Pip独有依赖(如果有) pip_only_deps: - some-pip-specific-pkg>=1.0 # 开发/文档构建依赖 dev_deps: - pytest>=7.0 - sphinx>=4.0 - black>=22.0
用Jinja2模板生成配置文件
把setup.cfg、meta.yml、environment.yml做成模板文件(比如setup.cfg.j2),然后写一个简单的Python脚本渲染生成最终配置:
示例模板 setup.cfg.j2
[metadata] name = your-package version = 0.1.0 [options] python_requires = >=3.8 install_requires = {% for dep in runtime_deps %} {{ dep }} {% endfor %} {% for dep in pip_only_deps %} {{ dep }} {% endfor %} [options.extras_require] dev = {% for dep in dev_deps %} {{ dep }} {% endfor %}
渲染脚本 generate_deps.py
import yaml from jinja2 import Template # 读取核心依赖 with open("dependencies.yaml") as f: deps = yaml.safe_load(f) # 渲染setup.cfg with open("setup.cfg.j2") as f: template = Template(f.read()) with open("setup.cfg", "w") as f: f.write(template.render(**deps)) # 渲染meta.yml with open("meta.yml.j2") as f: template = Template(f.read()) with open("meta.yml", "w") as f: f.write(template.render(**deps)) # 渲染environment.yml with open("environment.yml.j2") as f: template = Template(f.read()) with open("environment.yml", "w") as f: f.write(template.render(**deps))
每次依赖变更时,修改dependencies.yaml后运行脚本即可更新所有配置文件。
2. 直接在配置文件中复用已有依赖(无需额外脚本)
如果不想写脚本,可以利用配置文件的语法特性直接引用其他文件的依赖:
Conda的meta.yml引用setup.cfg的运行依赖
在meta.yml中用Jinja2语法读取setup.cfg的install_requires:
package: name: your-package version: "{{ version }}" source: path: .. requirements: build: - python - setuptools - wheel run: - python {% for line in open('../setup.cfg').read().split('install_requires =')[1].splitlines() %} {% if line.strip() %} - {{ line.strip() }} {% endif %} {% endfor %} # 添加Conda独有依赖 - libgfortran
Environment.yml复用项目依赖
在environment.yml中通过pip安装本地包并包含开发依赖,无需重复声明运行依赖:
name: your-dev-env channels: - conda-forge dependencies: - python>=3.8 - pip - pytest>=7.0 # 开发独有依赖 - sphinx>=4.0 - pip: - -e .[dev] # 复用setup.cfg中的运行依赖和开发依赖
3. 用pyproject.toml统一Setuptools配置
将Setuptools的运行依赖和构建依赖都放在pyproject.toml中,简化setup.cfg,同时让其他配置文件可以引用这个单一源:
示例pyproject.toml
[build-system] requires = ["setuptools>=61.0", "wheel>=0.37.0"] build-backend = "setuptools.build_meta" [project] name = "your-package" version = "0.1.0" dependencies = [ "requests>=2.25.0", "pandas>=1.3.0", "numpy>=1.21.0" ] [project.optional-dependencies] dev = [ "pytest>=7.0", "sphinx>=4.0", "black>=22.0" ]
然后setup.cfg可以只保留非依赖相关的配置,meta.yml同样可以用Jinja2读取pyproject.toml中的dependencies字段。
内容的提问来源于stack exchange,提问作者tierriminator
相关产品推荐
相关产品推荐

