如何在 conda 中限制包版本?

How to constrain package versions in conda?

我在预装了一堆包的 conda 环境中工作(conda 列表有 360 个包,很多 ML 工具和一些 bioconda)。我有时需要添加一个包;但是,我发现 conda install newpackage 通常非常慢(在“解决环境”中花费数小时或数天),如果它完成了,它通常会建议更新我真的不想接触的包。

我想固定一些核心包(python、numpy、scipy 等)的当前版本,以便 conda 甚至认为修改它们是不可能的。这既是为了速度,也是为了避免任何无意的更新。如果这意味着无法安装我想尝试添加的某个包,那没关系!我宁愿有一个像“newpackage 与你的 numpy 版本冲突”这样的快速回答,也不愿没有答案。然后我可以决定是否要忽略冲突;为这个包创建一个简单的环境; conda 在本地构建,或其他任何构建。

我该怎么做?

另请参阅:https://www.anaconda.com/blog/understanding-and-improving-condas-performance(未解决问题)

包固定

包可以在 per-environment 的基础上固定到特定版本。参见 the documentation on package pinning。例如,假设我们想要将 numpyscipy 固定到我们当前在名为 foo 的环境中拥有的确切版本。我们可以处理 conda list 的输出以匹配 Conda 固定规范的预期语法:

conda activate foo
conda list "^(numpy|scipy)$" | tail -n+4 | awk '{ print  " =="  }' > $CONDA_PREFIX/conda-meta/pinned

这里有几点需要注意:

  • conda list 采用正则表达式:利用它对您有利
  • tail 只是跳过 header
  • 这取决于在激活的环境中定义$CONDA_PREFIX
  • 这会覆盖任何现有的 pinned 文件

冻结安装

保持一切不变的劳动强度较低的方法是使用 --freeze-installed 标志。然而,在最新版本的 Conda 中,这在第一轮求解中默认使用。所以实际上这个标志现在所做的就是跳过第二轮解决方案,允许更新不属于明确规范的包。

PyPI 包

Pip 安装的 PyPI 包需要一些额外的配置才能让 Conda 固定它们。具体来说,需要在 envs/<env>/conda-meta/pinned 文件中使用以下语法:

numpy=1.21.4=pypi*

即表明pypi应该在构建字符串中。为了尊重这一点,必须启用 Pip 互操作性并允许灵活的通道优先级:

## settings only for this environment
conda activate foo
conda config --env --set pip_interop_enabled True
conda config --env --set channel_priority flexible

启用它会告诉 Conda 将 PyPI 包视为解决依赖关系的有效替代品。

就个人而言,我会小心使用它,因为 Conda 是一个通用的包管理器,有时通过 Pip 安装的包(例如 yamlwget)与 Conda 包不对应一样的名字。因此,为什么我在示例中使用 --env 仅在 within foo 环境中启用此配置设置。