2

I am making a conda virtual environment using an environment.yml file. In my package I want to use opencv version 4.1, from conda-forge. It installs great using the following line in the yml file:

- conda-forge::opencv=4.1

Unfortunately another package I'm including as a dependency has opencv-python as a dependency. Hence, once the environment is resolved, you end up with both opencv (version 4.1) and opencv-python (version 4.5) installed. This leads to problems when running my code.

Luckily, when I manually uninstall opencv-python everything works just fine in my package.

The problem is I don't want my github repo install instructions to be like: "Create this virtual environment with environment.yml file. Oh BTW you then need to enter pip uninstall opencv-python or else you will run into problems."

Is there a way to take care of this last pruning step in my environment.yml file, so things will just work out of the box?

Stuart Berg
  • 17,026
  • 12
  • 67
  • 99
eric
  • 7,142
  • 12
  • 72
  • 138
  • 1
    Looks like there is not yet any official support in conda for this feature. Here's the issue to track: https://github.com/conda/conda/issues/6805 – Stuart Berg Jan 29 '21 at 04:31
  • @StuartBerg thanks this is super helpful. Following. Seems it will be a really helpful feature for these kinds of corner cases. – eric Jan 29 '21 at 14:26

2 Answers2

2

I suppose you could create your own conda package, which will be mostly empty except for a special activation script in ${PREFIX}/etc/conda/activate.d/. The activation script will check if opencv-python is installed, and remove it.

This recipe would do it:

recipe/
├── meta.yaml
└── uninstall-opencv-python.sh
# meta.yaml
package:
  name: my-hack-to-uninstall-opencv-python
  version: 0.1

build:
  number: 0
  noarch: generic
  script:
   - mkdir -p {{ PREFIX }}/etc/conda/activate.d/
   - cp {{ RECIPE_DIR }}/uninstall-opencv-python.sh {{ PREFIX }}/etc/conda/activate.d/
# uninstall-opencv-python.sh
if (pip list | grep opencv-python > /dev/null); then
   echo "Uninstalling opencv-python"
   pip uninstall opencv-python
fi

Build that recipe and upload the resulting package to your own channel on anaconda.org. Then, add a line to your environment.yml file:

- mychannel::my-hack-to-uninstall-opencv-python

The only downside is that it will run that script every time the environment is activated. But it's a relatively fast script, so maybe that's not a problem. Obviously any solution to this particular problem will be somewhat of a hack, no matter what you come up with.

Stuart Berg
  • 17,026
  • 12
  • 67
  • 99
1

I don't want my github repo install instructions to be like ... "Oh BTW you then need to enter pip uninstall opencv-python..."

Well, what about the following commands instead?

# This extra line is necessary if running within a script,
# otherwise 'conda activate' is broken.
# https://github.com/conda/conda/issues/7980#issuecomment-441358406
source $(conda info --base)/etc/profile.d/conda.sh

conda create -n foo conda-dependencies.yml
conda activate foo
pip install --no-deps pypi-dependencies.txt

That's more than one command, but at least it doesn't involve an uninstall step.


To produce those two files for your users, run:

conda env export -f conda-dependencies.yml

...then remove the pypi dependencies from that file and copy them into pypi-dependencies.txt (with the appropriate syntax changes, of course). But delete the opencv-python line.

Stuart Berg
  • 17,026
  • 12
  • 67
  • 99
  • 1
    I really like this suggestion it is pretty simple, and I think I could incorporate it into a single shell script. Will test it tonight. I'm also wondering if just having them enter the uninstall manually might be not all that bad, but this is more elegant. – eric Jan 29 '21 at 14:25
  • 1
    It just occurred to me that (1) I forgot the `activate` step, and (2) you can't call `conda activate` within a script unless you run a special line in advance. See my edits above. – Stuart Berg Jan 29 '21 at 20:42