3

Simplified MWE => Suppose I have Anaconda and do the following:

conda create -n demo python=3.6
conda activate demo
conda install seaborn

The last command installs 39 new packages including seaborn, matplotlib and pandas. Now suppose that time passes and I continue to set up my environment and wish to explicitly install matplotlib and pandas:

conda install matplotlib pandas

This tells me "All requested packages already installed", which is okay. Now however, if I decide I don't need seaborn anymore and remove it,

conda remove seaborn

this removes ALL 39 packages that were installed when seaborn was installed, including both matplotlib and pandas, which I explicitly installed after that! How can I avoid this problem?

My expected behaviour would be that conda remove seaborn removes seaborn and all of its dependencies, but does not remove any package (or dependencies thereof) that was explicitly installed before or after seaborn. Some might say just uninstall seaborn and all 39 packages, and then manually reinstall matplotlib and pandas. This works in trivial cases, but once there are e.g. 25 packages with complex interdependencies, this becomes very complicated, and at the very least a complete nuisance to maintain.

As a concrete example of this, how can I construct a full Anaconda environment minus a particular package and only the packages that depend on it? I tried:

conda create -n test python=3.6 anaconda
conda remove libtiff  # I want this to strictly only remove libtiff and its recursive dependents, but obviously this is not what happens

but the second line removes essentially every single package in the entire environment as it removes anaconda. Any ideas?

pallgeuer
  • 1,216
  • 1
  • 7
  • 17
  • This is surprising behavior. I would [report this on the repo](https://github.com/conda/conda/issues). First, Conda fails to add requested packages to the explicit spec when already present (note: you can force this with `--force-reinstall`, e.g. on `matplotlib`, but I think it should do it by default). Second, it appears that Conda is aggressively pruning to the explicit spec when calling `conda remove`. The `conda env update` command requires an explicit `--prune` flag to behave like this, so it would make sense that something similar should be added to `conda remove`. – merv Oct 18 '19 at 01:06
  • BTW, by "explicit spec" I refer to the internal list of package specifications that Conda derives from looking at its transaction history (`conda-meta/history`). It's the stuff you have explicitly requested to be in your repo. You basically get a YAML copy of it when running `conda env export --from-history` – merv Oct 18 '19 at 01:09
  • Yeah, the behaviour of conda remove really doesn't seem to match what would be reasonably expected. Assuming that the behaviour of conda for now stays like that, is there still any way I can work around it to achieve what I described? – pallgeuer Oct 18 '19 at 22:30

1 Answers1

1

Workaround

I can't think of an automated way to do this, but if you absolutely must achieve this, then a hacky way to do it is:

  1. Remove only the package(s) you want:

    conda remove --force libtiff
    
  2. Trigger a consistency check to get a list of now broken packages:

    conda install -d python
    
  3. If there are packages, then iterate (i.e., remove them with Step 1); otherwise, you're done.

Actually, you're not done because now every time you attempt a change in the environment, every package that isn't a dependency of an explicit spec will be proposed for removal. Probably the next step is to:

  1. Export the resulting env:

    conda env export -n my_env > env.yaml
    
  2. Recreate the env:

    conda env remove -n my_env
    conda env create -n my_env -f env.yaml
    

Now all the packages will be explicit specs, which isn't necessarily a good thing either, but at least ensures they won't get removed on later updates.

Commentary

Personally, I think this is a bad idea and don't really see the motivation. I think it is much better an idea to start from the packages you know you need, place them in a YAML definition, and create envs from that.

merv
  • 67,214
  • 13
  • 180
  • 245
  • Would it maybe be a bit more efficient to first export and recreate the environment, and then remove libtiff? Would this achieve the same thing without the recursive steps 1-3? Also, in regard to the first half of my question, is there any way I can work around the problem that uninstalling packages can automatically remove packages that I've explicitly installed? – pallgeuer Oct 21 '19 at 16:49
  • @pallgeuer you might be right. On the other thing, `--force-reinstall` the packages you want added to spec. – merv Oct 21 '19 at 17:11