当我只想删除一个包时,为什么 conda 想要更新不相关的包?

Why does conda want to update unrelated packages when I want to remove just one?

Windows 10

conda 4.9.2(通过 miniconda)

我安装了一个包,不需要重新安装或升级任何其他依赖项。一旦我意识到我安装了一个不合适版本的包,我就去删除它,这是我看到的屏幕:

(pydata) PS C:\Users\Navneeth> conda remove xlrd
Collecting package metadata (repodata.json): done
Solving environment: |
Warning: 2 possible package resolutions (only showing differing packages):
  - defaults/win-64::libtiff-4.1.0-h56a325e_1, defaults/win-64::zstd-1.4.9-h19a0ad4_0
  - defaults/win-64::libtiff-4.2.0-hd0e1b90_0, defaults/win-64::zstd-1.4.5-h04227a9done

## Package Plan ##

  environment location: C:\Users\Navneeth\Miniconda3\envs\pydata

  removed specs:
    - xlrd


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    decorator-5.0.3            |     pyhd3eb1b0_0          12 KB
    importlib-metadata-3.7.3   |   py38haa95532_1          31 KB
    importlib_metadata-3.7.3   |       hd3eb1b0_1          11 KB
    ipython-7.22.0             |   py38hd4e2768_0         998 KB
    jupyter_client-6.1.12      |     pyhd3eb1b0_0          88 KB
    libtiff-4.1.0              |       h56a325e_1         739 KB
    nbformat-5.1.3             |     pyhd3eb1b0_0          44 KB
    notebook-6.3.0             |   py38haa95532_0         4.4 MB
    pandoc-2.12                |       haa95532_0        13.2 MB
    parso-0.8.2                |     pyhd3eb1b0_0          69 KB
    pillow-8.2.0               |   py38h4fa10fc_0         671 KB
    prometheus_client-0.10.0   |     pyhd3eb1b0_0          46 KB
    prompt-toolkit-3.0.17      |     pyh06a4308_0         256 KB
    terminado-0.9.4            |   py38haa95532_0          26 KB
    zipp-3.4.1                 |     pyhd3eb1b0_0          15 KB
    zstd-1.4.9                 |       h19a0ad4_0         478 KB
    ------------------------------------------------------------
                                           Total:        21.0 MB

The following packages will be REMOVED:

  xlrd-2.0.1-pyhd3eb1b0_0

The following packages will be UPDATED:

  decorator                              4.4.2-pyhd3eb1b0_0 --> 5.0.3-pyhd3eb1b0_0
  importlib-metadata pkgs/main/noarch::importlib-metadata-~ --> pkgs/main/win-64::importlib-metadata-3.7.3-py38haa95532_1
  importlib_metadata                                2.0.0-1 --> 3.7.3-hd3eb1b0_1
  ipython                             7.21.0-py38hd4e2768_0 --> 7.22.0-py38hd4e2768_0
  jupyter_client                                 6.1.7-py_0 --> 6.1.12-pyhd3eb1b0_0
  nbformat                               5.1.2-pyhd3eb1b0_1 --> 5.1.3-pyhd3eb1b0_0
  notebook                             6.2.0-py38haa95532_0 --> 6.3.0-py38haa95532_0
  pandoc                                    2.11-h9490d1a_0 --> 2.12-haa95532_0
  parso                                  0.8.1-pyhd3eb1b0_0 --> 0.8.2-pyhd3eb1b0_0
  pillow                               8.1.2-py38h4fa10fc_0 --> 8.2.0-py38h4fa10fc_0
  prometheus_client                      0.9.0-pyhd3eb1b0_0 --> 0.10.0-pyhd3eb1b0_0
  prompt-toolkit                                 3.0.8-py_0 --> 3.0.17-pyh06a4308_0
  sqlite                                  3.33.0-h2a8f88b_0 --> 3.35.3-h2bbff1b_0
  terminado                            0.9.2-py38haa95532_0 --> 0.9.4-py38haa95532_0
  zipp                                   3.4.0-pyhd3eb1b0_0 --> 3.4.1-pyhd3eb1b0_0
  zstd                                     1.4.5-h04227a9_0 --> 1.4.9-h19a0ad4_0

The following packages will be DOWNGRADED:

  libtiff                                  4.2.0-he0120a3_0 --> 4.1.0-h56a325e_1


Proceed ([y]/n)?

为什么 conda 要更新或降级所有这些其他软件包,而我安装 xlrd 时却没有执行相反的操作?有没有一种方法可以安全地删除 just xlrd. (我听说使用 --force 有风险。)

不对称

Conda 在删除时重新解决。在安装时,Conda 首先尝试冻结解决,这相当于保持所有已安装的包固定并仅搜索兼容的请求包版本。在这种特定情况下,xlrd (v2.1.0) 是一个 noarch,只有 python>=3.6 约束。所以这个安装在这个 frozen solve pass.

约束 xlrd 也将添加到显式规范中。1

删除时,Conda 会先删除约束,然后用新的一组显式规范重新求解环境。正是在这个解决方案中,Conda 识别出较新版本的包,然后建议更新。

因此,不对称之处在于冻结解决方案明确避免检查任何新包,但删除将触发此类检查。 目前没有办法在不绕过依赖性检查的情况下避免这种情况。


曼巴

实际上,mambaconda 的已编译(快速!)替代品,如果它没有任何依赖项,将仅删除指定的包。这是我测试中的默认行为。


附录:仍有一些无法解释的行为

我通过首先创建具有两个规范的环境来复制您的经验:

name: foo
channels:
  - conda-forge
dependencies:
  - python=3.8.0
  - pip=20

为了模拟这是一个旧环境,我进入 envs/foo/conda-meta/history 并更改了2

# update specs: ['pip=20', 'python=3.8.0']

# update specs: ['python=3.8']

随后 运行 conda install xlrd 按预期进行。然后 conda remove xlrd 给出了一个有点奇怪的结果:

## Package Plan ##

  environment location: /opt/conda/envs/foo

  removed specs:
    - xlrd


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    pip-21.1.1                 |     pyhd8ed1ab_0         1.1 MB  conda-forge
    ------------------------------------------------------------
                                           Total:         1.1 MB

The following packages will be REMOVED:

  xlrd-2.0.1-pyhd8ed1ab_3

The following packages will be UPDATED:

  pip                                   20.3.4-pyhd8ed1ab_0 --> 21.1.1-pyhd8ed1ab_0


Proceed ([y]/n)?

这有效地复制了 OP 结果,然而,这里的额外奇怪之处是 python 包不建议更新,即使我有意将其约束从 3.8.0 放松到 3.8。似乎 只有不在明确规范中的包在包删除期间才会更新


[1] 显式规范 是 Conda 对用户拥有的每个约束保留的内部维护记录明确规定。可以使用 conda env export --from-history 查看环境的当前明确规范。可以在 yourenv/conda-meta/history.

找到原始内部记录

[2] 不推荐!